【问题标题】:Match backslash followed by escape character匹配反斜杠后跟转义字符
【发布时间】:2015-04-14 09:05:37
【问题描述】:

我试图匹配一个反斜杠,后跟一个转义字符,如 tnr\.. 就像在 JSON 字符串中一样。为简化起见,只考虑\t\\.. 例如:

use feature qw(say);
use strict;
use warnings;
use Data::Dump qw(dump);

my @data = (
    [q{\t},    qr/\\t/],            #ok
    ["\\",     qr/\\/],             #ok
    ["\\",     qr/[\\]/],           #ok
    ["\t",     qr/\t/],             #ok
    ["\t",     qr/[\t]/],           #ok
    [q{\\\t},  qr/(\\[\\\t])*/],    #not ok
    [q{\\\t},  qr/(\\\\[\\\\t])*/ ],#ok
);

for my $i (0..$#data) {
    my ($str, $regex) = @{$data[$i]};
    my $match_result = ($str =~ /^$regex$/) ? "ok" : "not ok";
    say(
        "$i : "
         . dump( $str )
         . ' =~ '
         . dump( $regex )
         . ' : '
         . $match_result
     );
}

输出:

0 : "\\t" =~ qr/\\t/ : ok
1 : "\\" =~ qr/\\/ : ok
2 : "\\" =~ qr/[\\]/ : ok
3 : "\t" =~ qr/\t/ : ok
4 : "\t" =~ qr/[\t]/ : ok
5 : "\\\\t" =~ qr/(\\[\\\t])*/ : not ok
6 : "\\\\t" =~ qr/(\\\\[\\\\t])*/ : ok

问题是,为什么测试#5 会失败。我认为这将是正确的正则表达式。我在这里错过了什么?

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    第 5 项是

    q{\\\t} =~ qr/(\\[\\\t])*/
    

    q{\\\t},相当于'\\\t'。在单引号字符串中,除了

    之外不需要转义任何内容
    • 分隔符
    • 在结束分隔符或另一个反斜杠之前的反斜杠

    此外,任何两个反斜杠一起出现的情况都被视为转义的反斜杠。

    所以'\\\t'是一个包含\\t的三字符字符串。

    qr// 的内容表现为双引号上下文,所以 所有 反斜杠需要转义,并可能修改后面的字符。

    "(\\[\\\t])*"是由(\[\\t]])*组成的八字符字符串,其中\t\t的制表符.因此,您的模式将匹配由反斜杠后跟制表符或反斜杠组成的字符串,所有这些都重复零次或多次。字符串中只有反斜杠和t,因此无法匹配。

    我希望这会有所帮助。底线是单引号内除了保护反斜杠和分隔符外没有转义序列,而'\t' 的意思正是反斜杠,小写字母t

    【讨论】:

    • 感谢您的澄清!我至少错过了两件事。首先,q 中的双反斜杠算作单个反斜杠。所以q{\\\\\\t} 的七个字符参数变成了一个 4 个字符长度的字符串。第二件事是,正如您所指出的,\tqr 中变为\x09。所以我打算为测试#5 做的可能是[q{\\\\\\t}, qr/(\\[t\\])*/]
    • @HåkonHægland:听起来你已经掌握了它。许多人没有意识到,在单引号内,single 反斜杠被保留并且不需要加倍。这意味着像'C:\Windows\System32\drivers' 这样的Windows 路径很好。当您需要一个尾随反斜杠时,唯一的问题是确实 必须被转义,或者像\\SERVER\backup\20150415 这样的UNC 路径必须表示为'\\\\SERVER\backup\20150415'。 (实际上,开头只需要三个反斜杠,但四个似乎更好。)
    【解决方案2】:

    原因如下:

    q{\\\t}
    

    "\\\\t" 
    

    即 3 个字符,2 个反斜杠,后跟一个 't'

    您的正则表达式 #5 匹配任意数量的字符对(一个 \ 后跟另一个 \ 或 )

    改成

    [q{\\\t},  qr/(\\[\\\t]*)*/],    #not ok
    

    还是不行,

    但是

    [q{\\\t},  qr/(\\[\\t]*)*/],    #ok
    

    会起作用的。

    HTH 乔治

    【讨论】:

      猜你喜欢
      • 2017-06-24
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 2019-08-26
      • 2020-10-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多