2009-06-29 9 views
5

मैं एक रेगेक्स लिखने की कोशिश कर रहा हूं जो सबकुछ से मेल खाएगा लेकिन एक एस्ट्रोफ़े जो बच निकला नहीं है। निम्नलिखित पर विचार करें:तारों से मिलान करते समय regex बच निकला-उद्धरण कैसे अनदेखा कर सकता है?

<?php $s = 'Hi everyone, we\'re ready now.'; ?> 

मेरे लक्ष्य को रेगुलर एक्सप्रेशन कि अनिवार्य रूप से इस बात का स्ट्रिंग भाग की पूर्ति करेंगे, लिखने के लिए है। मैं के रूप में

/.*'([^']).*/ 

आदेश एक सरल स्ट्रिंग के मिलान में कुछ इस तरह की सोच रहा हूँ, लेकिन मैं यह पता लगाने की कैसे एक नकारात्मक lookbehind कि apostrophe पर काम कर सुनिश्चित करने के लिए है कि यह से पहले नहीं किया गया है प्राप्त करने की कोशिश कर रहा है बैकस्लैश ...

कोई विचार?

- JMT

उत्तर

3
<?php 
$backslash = '\\'; 

$pattern = <<< PATTERN 
#(["'])(?:{$backslash}{$backslash}?+.)*?{$backslash}1# 
PATTERN; 

foreach(array(
    "<?php \$s = 'Hi everyone, we\\'re ready now.'; ?>", 
    '<?php $s = "Hi everyone, we\\"re ready now."; ?>', 
    "xyz'a\\'bc\\d'123", 
    "x = 'My string ends with with a backslash\\\\';" 
    ) as $subject) { 
     preg_match($pattern, $subject, $matches); 
     echo $subject , ' => ', $matches[0], "\n\n"; 
} 

प्रिंट

<?php $s = 'Hi everyone, we\'re ready now.'; ?> => 'Hi everyone, we\'re ready now.' 

<?php $s = "Hi everyone, we\"re ready now."; ?> => "Hi everyone, we\"re ready now." 

xyz'a\'bc\d'123 => 'a\'bc\d' 

x = 'My string ends with with a backslash\\'; => 'My string ends with with a backslash\\' 
+0

मतदान करना क्योंकि आपने परीक्षण के मामले प्रदान किए हैं। –

2
/.*'([^'\\]|\\.)*'.*/ 

parenthesized भाग गैर अक्षर लोप/बैकस्लैश और बैकस्लैश-एस्केप्ड पात्रों के लिए लग रहा है। यदि केवल कुछ वर्ण बच निकले जा सकते हैं तो \\. से \\['\\a-z], या जो भी हो।

+0

बहुत करीब है, लेकिन उस रोग के मामले को संभाल नहीं करता है ... –

+0

धन्यवाद जॉन 'मेरा स्ट्रिंग एक बैकस्लैश \\ साथ साथ समाप्त होता है'! सौभाग्य से मेरे लिए, जिन मामलों के साथ मुझे निपटना होगा, उन्हें रोक दिया जा सकता है, और यह कभी भी उस समस्या तक नहीं पहुंच पाएगा जो .jxc वर्णन करता है। बहुत ही सरल समाधान, जिसमें से मुझे वास्तव में सोचना चाहिए था। फिर से धन्यवाद! :) – JMTyler

0

वाया पीछे नकारात्मक देखो:

/ 
.*?'    #Match until ' 
(
.*?    #Lazy match & capture of everything after the first apostrophe 
)  
(?<!(?<!\\)\\)' #Match first apostrophe that isn't preceded by \, but accept \\ 
.*    #Match remaining text 
/
0
Regex reg = new Regex("(?<!\\\\)'(?<string>.*?)(?<!\\\\)'"); 
3

यहाँ परीक्षण मामलों के साथ मेरे समाधान है:

/.*?'((?:\\\\|\\'|[^'])*+)'/ 

और मेरे (पर्ल, लेकिन मैं मुझे नहीं लगता कि किसी भी पर्ल विशिष्ट सुविधाओं का उपयोग नहीं करते हैं) सबूत:

use strict; 
use warnings; 

my %tests =(); 
$tests{'Case 1'} = <<'EOF'; 
$var = 'My string'; 
EOF 

$tests{'Case 2'} = <<'EOF'; 
$var = 'My string has it\'s challenges'; 
EOF 

$tests{'Case 3'} = <<'EOF'; 
$var = 'My string ends with a backslash\\'; 
EOF 

foreach my $key (sort (keys %tests)) { 
    print "$key...\n"; 
    if ($tests{$key} =~ m/.*?'((?:\\\\|\\'|[^'])*+)'/) { 
     print " ... '$1'\n"; 
    } else { 
     print " ... NO MATCH\n"; 
    } 
} 

चल रहा है इस से पता चलता:

$ perl a.pl 
Case 1... 
... 'My string' 
Case 2... 
... 'My string has it\'s challenges' 
Case 3... 
... 'My string ends with a backslash\\' 

नोट है कि कम से प्रारंभिक वाइल्डकार्ड शुरूआत गैर लालची होने की जरूरत है। फिर मैं गैर-बैकट्रैकिंग मैचों का उपयोग \\ और \ 'और फिर कुछ भी करने के लिए करता हूं जो एक स्टैंडअलोन उद्धरण चरित्र नहीं है।

मुझे लगता है कि यह शायद संकलक के अंतर्निहित दृष्टिकोण की नकल करता है, जो इसे बहुत बुलेट प्रूफ बनाना चाहिए।

0

यह जावा स्क्रिप्ट के लिए है:

/('|")(?:\\\\|\\\1|[\s\S])*?\1/

यह

...

  • मैचों एकल या डबल उद्धृत तार
  • मैचों रिक्त स्ट्रिंग (लंबाई 0)
  • मैचों तार के साथ एम्बेडेड व्हाइटस्पेस (\n, \t, आदि)
  • स्किप के भीतरी उद्धरण (एकल या डबल) दोहरे उद्धरण चिह्नों के भीतर
  • स्किप के एकल उद्धरण से बच गया और इसके विपरीत

केवल पहली बोली कब्जा कर लिया है। आप के साथ $ 2 में गैर उद्धृत स्ट्रिंग पर कब्जा कर सकते हैं:

/('|")((?:\\\\|\\\1|[\s\S])*?)\1/