2009-06-29 7 views
5

Ich versuche, eine Regex zu schreiben, die alles ABER einen Apostroph zusammenbringt, der nicht entkam. Berücksichtigen Sie Folgendes:Wie kann die Regex-Zeilenumbrüche bei der Suche nach Zeichenfolgen ignorieren?

Mein Ziel ist es, einen regulären Ausdruck zu schreiben, der im Wesentlichen den String-Teil davon entspricht. Ich denke an etwas wie

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

um einen einfachen String übereinstimmen, aber ich habe, um herauszufinden versucht, wie eine negative Lookbehind auf diesem Apostroph zum Laufen zu bringen, um sicherzustellen, dass es nicht vorangeht ein Backslash ...

Irgendwelche Ideen?

- JMT

Antwort

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"; 
} 

druckt

<?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

Abstimmung, weil Sie Testfälle bereitgestellt haben. –

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

Der klammerten Teil nicht-Apostroph/Schrägstriche und Backslash-Escape-Zeichen sucht. Wenn nur bestimmte Zeichen maskiert werden können, ändern Sie die \\. in \\['\\a-z] oder was auch immer.

+0

Sehr fast, aber das dem pathologischen Fall nicht behandeln ... ‚Meine Zeichenfolge endet mit mit einem Backslash \\‘ –

+0

Dank John! Zum Glück für mich können die Fälle, mit denen ich mich befassen muss, zurückgehalten werden und werden niemals das Problem erreichen, das in der .jxc beschrieben wird. Sehr einfache Lösung, an die ich wirklich hätte denken sollen. Nochmals vielen Dank! :) – JMTyler

0

Via negativen Blick hinter:

/ 
.*?'    #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

Hier ist meine Lösung mit Testfällen:

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

Und meine (Perl, aber ich habe keine Perl-spezifischen Funktionen verwenden Ich glaube nicht) Beweis:

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"; 
    } 
} 

Laufen dies zeigt:

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

Beachten Sie, dass die anfängliche Wildcard bei der Start muss nicht gierig sein. Dann verwende ich Nicht-Backtracking-Matches, um \\ und \ 'und dann alles, was kein eigenständiges Anführungszeichen ist, verschlingen zu können.

Ich denke, dass dieser wahrscheinlich den eingebauten Ansatz des Compilers nachahmt, der es ziemlich kugelsicher machen sollte.

0

Dies ist für JavaScript:

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

es ...

  • Matches Einzel- oder Doppel Strings in Anführungszeichen
  • leere Strings Matches (Länge 0)
  • Matches Saiten eingebettete Leerzeichen (\n, \t usw.))
  • springen innere entkommen Anführungszeichen (einfach oder doppelt)
  • Hochkommata Sprünge in doppelten Anführungszeichen und vice versa

Nur das erste Zitat aufgenommen wird. Sie können den String ohne Anführungszeichen in $ 2 mit erfassen:

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