有人可以帮助我理解为什么以下正则表达式匹配时,我希望它不匹配。
要检查的字符串
/opt/lnpsite/ni00/flat/tmp/Med_Local_Bak/ROI_Med_Transfer/CBD99_PINPUK_14934_09_02_2017_12_07_36.txt
正则表达式
(?<!Transfer\/)\w*PINPUK.*(?:csv|txt)$
我希望这不匹配,因为字符串Transfer/
出现在0个或更多字符之后,后面跟着字符串PINPUK
。如果我将模式从\w*
更改为\w{6}
以显式匹配6个字符字符,则会正确返回不匹配项。
有人可以帮助我理解为什么在我的&#34; word&#34;上使用0或更多量词。正则表达式导致匹配?
答案 0 :(得分:3)
您的正则表达式模式(?<!Transfer/)\w*PINPUK.*(?:csv|txt)$
正在寻找\w*PINPUK
而不是,紧接着Transfer/
给出字符串
/opt/lnpsite/ni00/flat/tmp/Med_Local_Bak/ROI_Med_Transfer/CBD99_PINPUK_14934_09_02_2017_12_07_36.txt
正则表达式引擎将首先将\w*PINPUK
与CBD99_PINPUK
但是前面有Transfer/
,因此引擎回溯并找到BD99_PINPUK
前面有C
,不是Transfer/
,所以匹配成功
至于修正,只需将斜线放在后面的
之外(?<!Transfer)/\w*PINPUK.*(?:csv|txt)$
强制\w*
在斜杠后立即开始,模式现在正确失败
答案 1 :(得分:2)
鲍罗丁已经很好地解释了为什么这不起作用并且解决了这种情况(移动a /)。有时像这样简单的东西是不可能的,尽管如此我在这里解释一个可能有用的替代工作
如果你将\w*
移到负面的后卫中,事情就会像你期望的那样匹配。像这样:
(?<!Transfer\/\w*)PINPUK.*(?:csv|txt)$
不幸的是,Perl不允许这样做,负面观察必须是固定的宽度。但仍有一种方法可以执行一次匹配:反向匹配
^(?:vsc|txt).*KUPNIP(?!\w*\/refsnarT)
这使用了可变长度的负向前瞻,这是Perl允许的。将所有这些放在一个脚本中我们得到
use strict;
use warnings;
use feature 'say';
my $string_matches = '/opt/lnpsite/ni00/flat/tmp/Med_Local_Bak/ROI_Med_Transfer/CBD99_PINPUK_14934_09_02_2017_12_07_36.txt';
say "Trying $string_matches";
if ( reverse($string_matches) =~ /^(?:vsc|txt).*KUPNIP(?!\w*\/refsnarT)/ ) {
say 'It matched';
} else {
say 'No match';
}
say '';
my $string_doesnt_match = '/opt/lnpsite/ni00/flat/tmp/Med_Local_Bak/ROI_Med/CBD99_PINPUK_14934_09_02_2017_12_07_36.txt';
say "Trying $string_doesnt_match";
if ( reverse($string_doesnt_match) =~ /^(?:vsc|txt).*KUPNIP(?!\w*\/refsnarT)/ ) {
say 'It matched';
} else {
say 'No match';
}
哪个输出
Trying /opt/lnpsite/ni00/flat/tmp/Med_Local_Bak/ROI_Med_Transfer/CBD99_PINPUK_14934_09_02_2017_12_07_36.txt
No match
Trying /opt/lnpsite/ni00/flat/tmp/Med_Local_Bak/ROI_Med/CBD99_PINPUK_14934_09_02_2017_12_07_36.txt
It matched