当匹配字符串时,正则表达式如何忽略转义引号?

时间:2009-06-29 21:17:21

标签: regex escaping negative-lookbehind

我正在尝试编写一个匹配所有内容的正则表达式但是没有被转义的撇号。请考虑以下事项:

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

我的目标是编写一个基本匹配字符串部分的正则表达式。我想的是像

这样的东西
/.*'([^']).*/

为了匹配一个简单的字符串,但我一直在试图弄清楚如何在该撇号上使用负面的lookbehind来确保它没有反斜杠......

有什么想法吗?

- JMT

6 个答案:

答案 0 :(得分: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\\'

答案 1 :(得分:3)

这是我的测试用例解决方案:

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

我的(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\\'

请注意,开头的初始通配符需要非贪婪。然后我使用非回溯匹配来吞噬\\和\',然后是其他任何不是独立引号字符的东西。

我认为这个可能模仿编译器的内置方法,这应该使它非常防弹。

答案 2 :(得分:2)

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

带括号的部分查找非撇号/反斜杠和反斜杠转义字符。如果只能转义某些字符,请将\\.更改为\\['\\a-z]或其他任何内容。

答案 3 :(得分: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
/

答案 4 :(得分:0)

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

答案 5 :(得分:0)

这适用于JavaScript:

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

它...

  • 匹配单引号或双引号字符串
  • 匹配空字符串(长度为0)
  • 匹配具有嵌入空格的字符串(\n\t等)。
  • 跳过内部转义引号(单引号或双引号)
  • 在双引号内跳过单引号,反之亦然

仅捕获第一个引用。您可以使用以下内容捕获$ 2中未加引号的字符串:

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