Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Perl抱怨\Q..\E regex节中的括号不匹配?_Regex_Perl - Fatal编程技术网

为什么Perl抱怨\Q..\E regex节中的括号不匹配?

为什么Perl抱怨\Q..\E regex节中的括号不匹配?,regex,perl,Regex,Perl,我在一个变量中有一个正则表达式,它在\Q..\E中包含一个子字符串,其中包含一个左括号。我希望解析器将[解释为普通字符,因为它位于\Q..\E节中 当正则表达式作为文本出现在程序中时,似乎就是这种情况,但当它出现在变量中时,解析器就失败了 这里有一个简化的例子 这项工作: $r = qr/\Qa[b\E\d+/; if ("a[b1" =~ $r) { print "match\n"; } 这失败了: $v='\Qa[b\E\d+'; $r=qr/$v/; 它在2号线死了 无与伦比的[在正则

我在一个变量中有一个正则表达式,它在
\Q..\E
中包含一个子字符串,其中包含一个左括号。我希望解析器将
[
解释为普通字符,因为它位于
\Q..\E
节中

当正则表达式作为文本出现在程序中时,似乎就是这种情况,但当它出现在变量中时,解析器就失败了

这里有一个简化的例子

这项工作:

$r = qr/\Qa[b\E\d+/;
if ("a[b1" =~ $r) { print "match\n"; }
这失败了:

$v='\Qa[b\E\d+';
$r=qr/$v/;
它在2号线死了


无与伦比的[在正则表达式中;标记为的Perl正则表达式首先被当作一个简单的双引号字符串进行求值。任何嵌入变量都会被插值,而非源自插值变量的转义序列都会被处理。这就是像
\L
\U
\Q...E
这样的特殊运算符是继续

处理在双引号字符串中停止,但在正则表达式中,该字符串随后被编译

在你的例子中,你有

$v = '\Qa[b\E\d+';
因为您使用了单引号,所以这个字符串根本没有改变

然后使用

$r = qr/$v/;
但是,由于插值变量内的转义序列未被触及,因此字符串会按原样传递给正则表达式编译器,该编译器会报告该表达式无效,因为它包含一个不匹配的未转义的开括号。如果删除该括号,仍然会出现错误;这次是
未识别的转义\Q在中传递regex
显示
\Q..\E
未被处理并显示为文本

工作方法是将作业更改为
$v
,改为使用双引号,如下所示

my $v = "\Qa[b\E\\d+";

必须将
\d
上的反斜杠加倍,否则is将消失。现在
\Q..\E
已生效,
$v
等于
a\[b\d+
。将其编译为正则表达式很好。

\Q
与正则表达式无关。当正则表达式引擎看到
\Q
时,它不识别它,发出警告,并将其视为
\\Q

>perl -we"$re='\Qa'; qr/$re/
Unrecognized escape \Q passed through in regex; marked by <-- HERE in m/\Q <-- HERE a/ at -e line 1.
解决方案:

  • $v=“\Qa[b\E\\d+”;
  • $v=qr/\Qa[b\E\d+/;
  • $v=quotemeta('a[b')。\d+';

解析正则表达式时会解释\Q和\E元字符。它们不是正则表达式本身的一部分。如果\Q和\E出现在正则表达式文本中,它们会告诉解析器忽略正则表达式中通常具有特殊含义的字符,包括括号。如果\Q和\E出现在单引号中,则作为变量赋值的一部分,它们被视为文字字符串。然后在正则表达式中使用此变量时,文字值成为正则表达式的一部分。反斜杠被解释为转义符,因此\Q与文字Q匹配,\E与文字E匹配

要查看此信息,请尝试编译正则表达式,然后打印它:

$v=qr/\Qa[b\E\d+/;
print "$v\n";
输出为:

(?-xism:a\[b\d+)
请注意,\Q和\E已消失,括号已转义。如果您分配的字符串在单引号内分别包含\Q和\E:

$v='ab\Qcd\Eef';
$r=qr/$v/;
print "$r\n";
你会得到:

(?-xism:ab\Qcd\Eef)
此正则表达式实际上与“abQcdEef”匹配:

结果:

matches

@ikegami:你说得对,但是你的代码没有演示它,因为变量内的转义序列始终没有被触及。这个
perl-E“表示qr/\t/,qr/\x09/,qr/\n/,qr/\x0A/”
确实如此,我很惊讶,因为它意味着正则表达式的双引号处理与标准字符串的处理不同。(
“\t”eq“\x09”
但是
qr/\t/ne qr/\x09/
)如果你想让正则表达式引擎能够理解像
\t
这样的东西,你最好还是让
\t
保持可读性。OTOH,
\N{…}
被转换成
\N{U+…}
,如果你使用用户定义的名字。
perl-Mcharnames=:full-E“说qr/\N{带锐音符的拉丁文小写字母E}/“
我从这个答案中了解到,我试图处理的正则表达式是错误的。我无法更改它,它是我的代码中的一个变量。我问题的前提是,
\Q..\E
是一个正则表达式语法构造。因为它一开始就错了,所以问题的其余部分没有意义。谢谢你的解释。@Daniel Vér是的,严格。
$v='ab\Qcd\Eef';
$r=qr/$v/;
if("abQcdEef" =~ /$r/) {print "matches\n"} else {print "no match\n"}
matches