我正在尝试执行匹配的正则表达式,如果单词cat和dog都在正则表达式中以任何顺序支持多行支持
matches
cat asdjfaldsfj dog
####
does NOT match
cat adfasdf8989
####
matches
dog adlsjf88989 cat
####
matches
cat asdf8a89sdf8
a sdf asd f ads f ads fasdf
dog a dsf ads fads f
asdfadsfadsf
我正在使用的正则表达式非常简单
/^(?=.*\bcat\b)(?=.*\bdog\b).*$/gs
问题是,这只会发现第一次出现,因为它是贪婪的。我真的希望以下内容计算两场比赛,但它只匹配一次
cat asdf8a89sdf8
a sdf asd f ads f ads fasdf
dog a dsf ads fads f
asdfadsfadsf
cat asdf8a89sdf8
a sdf asd f ads f ads fasdf
dog a dsf ads fads f
asdfadsfadsf
即使没有第二套猫STUFF狗STUFF,正则表达式仍然匹配到最后。
我使用regex101.com进行测试。
答案 0 :(得分:0)
主要问题是你没有使用贪婪量词;您使用^
锚点以及前瞻和.*
使用它。该模式别无选择,只能匹配所有内容或无需匹配。
相反,只需删除前瞻方法,然后将cat
和dog
与之间的任何内容匹配,或者相反:
/cat.*?dog|dog.*?cat/gs
在这种情况下,您确实需要使用?
指定延迟量词,否则它会像您所担心的那样将所有匹配作为一个匹配。
答案 1 :(得分:0)
只是一个建议,但也许这比复杂的正则表达式更具可读性
use List::MoreUtils 'all';
my @things = qw( cat dog bird fish );
for my $line ( @lines ) {
if ( all { $line =~ / \b $_ \b /x } @things ) {
# DO STUFF
}
}
all
功能是List::MoreUtils的一部分,但也可在List::AllUtils和List::SomeUtils中找到
此实现依赖于您逐行处理字符串,因此您可能会执行for my line ( split(/\n/, $string) ) { ... }
答案 2 :(得分:0)
CAustin的答案可以简化为:
/(cat|dog).*?(?!\1)(?:cat|dog)/gs
更容易扩展到更多字符串。有4个字符串:
/(cat|dog|bird|fish).*?(?!\1)(cat|dog|bird|fish).*?(?!\1|\2)(cat|dog|bird|fish).*?(?!\1|\2|\3)(?:cat|dog|bird|fish)/gs
并限制一些无用的回溯:
/(cat|dog|bird|fish)(?>.*?(?!\1)(cat|dog|bird|fish))(?>.*?(?!\1|\2)(cat|dog|bird|fish))(?>.*?(?!\1|\2|\3)(?:cat|dog|bird|fish))/gs