我要匹配一个存储在变量中的正则表达式:
#!/bin/env perl
use warnings;
use strict;
my $expr = qr/\s*(\w+(\[\d+\])?)\s+(\w+(\[\d+\])?)/sx;
$str = "abcd[3] xyzg[4:0]";
if ($str =~ m/$expr/) {
print "\n%%%%%%%%% $`-----$&-----$'\n";
}
else {
print "\n********* NOT MATCHED\n";
}
但是我在$&如
%%%%%%%%% -----abcd[3] xyzg-----[4:0]
但是期待,它不应该进入if子句。 目的是:
if $str = "abcd xyzg" => %%%%%%%%% -----abcd xyzg----- (CORRECT)
if $str = "abcd[2] xyzg" => %%%%%%%%% -----abcd[2] xyzg----- (CORRECT)
if $str = "abcd[2] xyzg[3] => %%%%%%%%% -----abcd[2] xyzg[3]----- (CORRECT)
if $str = "abcd[2:0] xyzg[3] => ********* NOT MATCHED (CORRECT)
if $str = "abcd[2:0] xyzg[3:0] => ********* NOT MATCHED (CORRECT)
if $str = "abcd[2] xyzg[3:0]" => ********* NOT MATCHED (CORRECT/INTENDED)
但输出为%%%%%%%%% -----abcd[2] xyzg-----[3:0] (WRONG)
或者更好地说这不是故意的。
在这种情况下,它应该/ my_expectation转到else块。
即使我不知道,为什么 $& 取一部分字符串( abcd [2] xyzg )和 $'的 [3:0] ?
如何?
它应该匹配完整,而不是像上面那样的部分。如果没有,则不应转到 if 子句。
任何人都可以帮我改变我的$ expr模式,以便我可以拥有预期的目标吗?
答案 0 :(得分:4)
默认情况下,Perl正则表达式只查找给定字符串的匹配子字符串。为了强制对整个字符串进行比较,您需要指明正则表达式从字符串的开头开始,并在结尾处使用^
和$
结束:
my $expr = qr/^\s*(\w+(\[\d+\])?)\s+(\w+(\[\d+\])?)$/;
(另外,没有理由拥有/x
修饰符,因为你的正则表达式不包含任何文字空格或#
字符,并且/s
修饰符没有理由,因为你没有使用.
。)
编辑:如果你不希望正则表达式匹配整个字符串,但是你希望它拒绝匹配部分后跟“[0:0]”之类的东西,最简单的方法就是使用前瞻:
my $expr = qr/^\s*(\w+(\[\d+\])?)\s+(\w+(\[\d+\]|(?=[^[\w])|$ ))/x;
这将匹配采用以下形式的任何内容:
[
,一个或多个数字,]
[
,一个或多个数字,]
[
也不是单词字符的字符(排除单词字符是为了防止正则表达式引擎在“a[0] bc[1:2]
”上成功仅匹配“a[0] b
”。)$
之后需要一个空格以防止它与以下)
合并以形成特殊变量的名称,这需要重新引入{{1}选项。)您是否还有其他需要满足的未说明要求?
答案 1 :(得分:1)
简短的回答是你的正则表示错误 如果没有您完全解释您的需求,我们无法为您解决这个问题,并且社区不会完全为您的目的编写正则表达式,因为这只是一个本地化的问题,只能帮助您这一次。
你需要问一些关于正则表达式的更一般的问题,我们可以向你解释,这将有助于你修复正则表达式,并帮助其他人修复它们。
当您在测试正则表达式时遇到问题,这是我的一般答案。使用正则表达式工具,例如regex buddy。
所以我要给出一个关于你在这里忽略的具体答案:
让我们让这个例子更小:
您的模式为a(bc+d)?
。它将匹配:abcd
abccd
等。虽然在bcd
的情况下它不匹配bzd
也不匹配abzd
,但它仅匹配{{1}因为整个a
组是可选的。同样,它会将bc+d
与abcbcd
匹配,从而删除无法匹配的整个可选组(在第二个a
处)。
正则表达式将匹配尽可能多的字符串,并在它们匹配某些内容并满足整个模式时返回真正的匹配。如果你做了一些可选的东西,当他们必须在它出现和匹配时必须包括它时,它们会把它留下来。
这是你尝试过的:
b
首先,此处不需要qr/\s*(\w+(\[\d+\])?)\s+(\w+(\[\d+\])?)/sx
和s
修饰符
其次,这个正则表达式可以匹配:
任何或没有空格后跟
至少包含一个字母字符的单词后跟
可选地,带有至少一个数字(例如[0]或[9999])的分组方括号括号后跟
至少有一个空格,后跟
至少包含一个字母字符的单词后跟
可选的方括号括号,至少有一位数。
显然,当你要求它匹配x
时,冒号结束abcd[0] xyzg[0:4]
模式但不满足\d+
所以它会回溯整个组,然后愉快地发现组是可选的。因此,如果不匹配最后一个可选组,则您的模式已成功匹配。