Как регулярное выражение может игнорировать экранированные кавычки при сопоставлении строк? - PullRequest
5 голосов
/ 30 июня 2009

Я пытаюсь написать регулярное выражение, которое будет соответствовать всему, НО апострофу, который не избежал. Учтите следующее:

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

Моя цель - написать регулярное выражение, которое будет по существу соответствовать строковой части этого. Я думаю о чем-то таком, как

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

для сопоставления с простой строкой, но я пытался выяснить, как получить отрицательный взгляд, работающий над этим апострофом, чтобы гарантировать, что ему не предшествует обратный слеш ...

Есть идеи?

- JMT

Ответы [ 6 ]

3 голосов
/ 30 июня 2009

Вот мое решение с тестовыми примерами:

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

И мое (Perl, но я не использую никаких специфических для Perl функций, я не думаю) доказательство:

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\\'

Обратите внимание, что начальный шаблон в начале должен быть не жадным. Затем я использую несоответствующие совпадения, чтобы сожрать \\ и \ ', а затем все, что не является отдельным символом кавычки.

Я думаю, что этот, вероятно, имитирует встроенный подход компилятора, что должно сделать его довольно пуленепробиваемым.

3 голосов
/ 30 июня 2009
<?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\\'
2 голосов
/ 30 июня 2009
/.*'([^'\\]|\\.)*'.*/

Часть, заключенная в скобки, ищет не-апострофы / обратные слэши и символы с обратной косой чертой. Если можно экранировать только определенные символы, измените значение \\. на \\['\\a-z] или любое другое.

0 голосов
/ 02 июля 2015

Это для JavaScript:

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

это ...

  • соответствует одинарным или двойным кавычкам
  • соответствует пустым строкам (длина 0)
  • соответствует строкам со встроенным пробелом (\n, \t и т. Д.)
  • пропускает внутренние экранированные кавычки (одинарные или двойные)
  • пропускает одинарные кавычки в двойных и наоборот

Только первая цитата захватывается. Вы можете записать строку без кавычек в $ 2 с помощью:

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

0 голосов
/ 30 июня 2009
Regex reg = new Regex("(?<!\\\\)'(?<string>.*?)(?<!\\\\)'");
0 голосов
/ 30 июня 2009

через отрицательный взгляд позади:

/
.*?'              #Match until '
(
 .*?              #Lazy match & capture of everything after the first apostrophe
)    
(?<!(?<!\\)\\)'   #Match first apostrophe that isn't preceded by \, but accept \\
.*                #Match remaining text
/
...