5 Stimmen

Wie kann regex ignorieren escaped-quotes beim Abgleich von Zeichenfolgen?

Ich versuche, eine Regex zu schreiben, die alles ABER ein Apostroph, das nicht escaped wurde, findet. Betrachten Sie das Folgende:

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

Mein Ziel ist es, einen regulären Ausdruck zu schreiben, der im Wesentlichen mit dem String-Teil davon übereinstimmen wird. Ich denke an etwas wie

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

um eine einfache Zeichenkette abzugleichen, aber ich habe versucht, herauszufinden, wie man ein negatives lookbehind auf das Apostroph arbeiten zu bekommen, um sicherzustellen, dass es nicht von einem Backslash vorangestellt wird...

Irgendwelche Ideen?

- JMT

4voto

the.jxc Punkte 3237

Hier ist meine Lösung mit Testfällen:

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

Und mein (Perl, aber ich benutze keine Perl-spezifischen Funktionen, glaube ich) 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";
    }
}

Die Durchführung dieser Shows:

$ 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 der anfängliche Platzhalter am Anfang nicht gierig sein muss. Dann verwende ich Non-Backtracking-Matches, um die \\ und \' und dann alles andere, was kein eigenständiges Zitatzeichen ist.

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

3voto

VolkerK Punkte 93746
<?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 Stimmen

Abstimmen, weil Sie Testfälle bereitgestellt haben.

2voto

John Kugelman Punkte 327535
/.*'([^'\\]|\\.)*'.*/

Der geklammerte Teil sucht nach Nicht-Apostrophen/Backlashes und Backslash-escaped-Zeichen. Wenn nur bestimmte Zeichen escaped werden können, ändern Sie die \\. à \\['\\a-z] oder was auch immer.

0 Stimmen

Fast, aber das behandelt nicht den pathologischen Fall... 'Mein String endet mit einem Backslash \\ '

0 Stimmen

Danke John! Zu meinem Glück lassen sich die Fälle, mit denen ich zu tun haben werde, in Grenzen halten und werden nie das Problem erreichen, das the.jxc beschreibt. Eine sehr einfache Lösung, an die ich wirklich hätte denken müssen. Nochmals vielen Dank! : )

0voto

patjbs Punkte 4252
Regex reg = new Regex("(?<!\\\\)'(?<string>.*?)(?<!\\\\)'");

0voto

aMarCruz Punkte 1788

Dies ist für JavaScript:

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

es...

  • passt zu Zeichenfolgen in einfachen oder doppelten Anführungszeichen
  • findet leere Zeichenfolgen (Länge 0)
  • findet Zeichenketten mit eingebetteten Leerzeichen ( \n , \t , usw.)
  • überspringt innere geschützte Anführungszeichen (einfach oder doppelt)
  • überspringt einfache Anführungszeichen innerhalb von doppelten Anführungszeichen und umgekehrt

Es wird nur das erste Zitat erfasst. Sie können die Zeichenkette ohne Anführungszeichen in $2 mit erfassen:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X