Perl,动态生成的带有反斜杠元字符的regexp字符串奇怪的行为

Perl,动态生成的带有反斜杠元字符的regexp字符串奇怪的行为,regex,perl,Regex,Perl,下面是一个小的perl代码片段: my $n = 1; my $re_str = '\d'; my $re_str_q = '\Q1\E'; printf "re_str match: %s\n", ($n =~ /$re_str/); printf "re_str_q match: %s\n", ($n =~ /$re_str_q/); printf "direct match: %s\n", ($n =~ /\Q1\E/); 运行时产生以下输出: re_str match: 1

下面是一个小的perl代码片段:

my $n = 1;
my $re_str = '\d';
my $re_str_q = '\Q1\E';

printf "re_str   match: %s\n", ($n =~ /$re_str/);
printf "re_str_q match: %s\n", ($n =~ /$re_str_q/);
printf "direct match: %s\n", ($n =~ /\Q1\E/);
运行时产生以下输出:

re_str   match: 1
re_str_q match: 
direct match: 1
所以,我这里的问题是为什么第二个
printf
不匹配?

如果您更改

my $re_str_q = '\Q1\E'; #from 
my $re_str_q = qr/\Q1\E/; #to
哪种方法是传递动态生成的正则表达式的正确方法,那么它将给出以下结果

re_str   match: 1
re_str_q match: 1
direct match: 1
如果你用过

use strict;
use warnings;
你会得到警告的

Unrecognized escape \Q passed through in regex; marked by <-- HERE in m/\Q <-- HERE 1\E/ at so.pl line 9.
Unrecognized escape \E passed through in regex; marked by <-- HERE in m/\Q1\E <-- HERE / at so.pl line 9.
有关\Q引用的字符的确切定义,请参阅

\L、\U、\F和\Q可以堆叠,在这种情况下,每个都需要一个\E。例如:

say"This \Qquoting \ubusiness \Uhere isn't quite\E done yet,\E is it?";
This quoting\ Business\ HERE\ ISN\'T\ QUITE\ done\ yet\, is it?

\Q和\E都由字符串插值处理,而不是由正则表达式引擎处理。在第一行和第二行
printf
中绕过字符串插值。在Perl编程中搜索“七种翻译转义”以获得对此的讨论。它们是:
\N{…}\U\U\L\L\E\Q\F
。(不要问我为什么有八个。)

您使用单引号来构建“动态生成的regexp”。使用
use warnings
perl将告诉您:


无法识别的转义\Q在正则表达式中传递;标记为的\Q不是正则表达式转义,它是字符串中替换的字符串转义,因此“\Q1\E”将等效于quotemeta('1')


因此,您需要使用可以插入这些序列的引号,如“”或qr/,或者调用quotemeta,而不是尝试使用字符串转义。

正则表达式涉及两种转义

  • 解析文本时处理的转义
  • 由正则表达式引擎处理的转义
比如说,

  • \Q..\E
    是前一种
  • \d
    是后一种
  • \n
    是两种类型
也就是说

  • “abc\Q!@#\Edef”
    生成12个字符的字符串
    abc\\@\#def
  • qq/abc\Q@#\Edef/
    完全是一样的
  • qr/abc\Q@#\Edef/
    生成12个字符的字符串
    abc\\@\#def
    ,然后将其编译为与9个字符相匹配的正则表达式模式@#def
但是单引号不能处理这种转义,所以

  • 'abc\Q@#\Edef'
    生成13个字符的字符串
    abc\Q@#\Edef
正则表达式引擎不理解
\Q
\E
,因此如果您最终将最后一个字符串传递给它,它将发出警告,然后它将尝试匹配11个字符
abcQ@#Edef

解决办法是改变

my $re_str   = '\d';         # Produces string \d
my $re_str_q = '\Q1\E\';     # Produces string \Q1\E

或者更好

my $re_str   = qr/\d/;       # Produces regex \d
my $re_str_q = qr/\Q1\E/;    # Produces regex \1


详细了解
\

+1解释
\d
\Q
,这似乎让人困惑OP@TLP,提供了一份参考文件,该文件将进一步详细解释。
my $re_str   = "\\d";        # Produces string \d
my $re_str_q = "\Q1\E";      # Produces string \1
my $re_str   = qr/\d/;       # Produces regex \d
my $re_str_q = qr/\Q1\E/;    # Produces regex \1