我只是写下:
if $_ =~ /abc|bcd/ && $_ !~ /diy/
如何在一个正则表达式中编写它。 perl
或grep
都可以。感谢。
答案 0 :(得分:3)
另一个答案中建议的前瞻/后方不适用于此问题。要使用lookbehind,你需要可变长度的lookbehind,perl不支持。
/^(?!.*?diy).*?(?:abc|bcd)/s
另一种方法:
/^(?:(?!diy).)*(?:abc|bcd(?!iy))(?:(?!diy).)*\z/s
在任何一种情况下,将bc从|中分解出来可以产生更有效的正则表达式。
答案 1 :(得分:2)
否定一系列字符通常是正则表达式中的一种痛苦。你必须使用预见断言。
如果您正在测试连续序列,您可以尝试使用前瞻和后视,例如(?<!diy)(abc|bcd)(?!diy)
,但这可能是模棱两可的。
我会像你一样离开测试,只丢失默认变量:
if /(abc|bcd)/ and not /diy/
清除干净。 :)
答案 2 :(得分:2)
当然,正则表达式可以使用一些先行断言
$i =~ /^(?=.*(?:abc|bcd))(?!.*diy)/
如果您想要其中一个部分, (?=.*(?:abc|bcd))
将成立
如果你不想要的字符串在那里,
(?!.*diy)
将会失败
但我认为你的解决方案更清晰。
答案 3 :(得分:1)
$ echo 'now I know my abcs' | txr -c '@/.*(abc|bcd).*&~.*diy.*/' -
$ echo 'no match' | txr -c '@/.*(abc|bcd).*&~.*diy.*/' -
false
$ echo 'Kaz wanted better regex, so he did the diy thing, starting from abc' | txr -c '@/.*(abc|bcd).*&~.*diy.*/' -
false
false
伴随着终止状态失败,并表示不匹配。没有输出意味着匹配。
我们使用.*
,因为匹配是锚定的。 @/RE/
本身在一行上意味着该行必须与正则表达式匹配;也就是说,当我们将该线路送到正则表达式机器时,从开始到结束,机器都处于接受状态。
当你有这样的正则表达式时,在正则表达式中使用搜索语义是不好的。即如果foo
实际上意味着.*(foo).*
(在文本中的任何位置匹配foo
),那对于foo&~bar
来说效果不佳,因为.*(foo&~bar).*
并不意味着相同作为.*foo.*&~.*bar.*
的事情。前者表示“匹配任何具有匹配foo&~bar
的子字符串的字符串。”但这是一场不可能的比赛;没有字符串可以同时为foo
和bar
。这是一个空的十字路口。但后者意味着“匹配其中包含foo
的字符串,但在任何地方都不包含bar
。”现在你正在做生意。