【发布时间】:2012-03-28 02:40:44
【问题描述】:
我只是这样写:
if $_ =~ /abc|bcd/ && $_ !~ /diy/
如何在一个正则表达式中编写它。 perl 或 grep 都可以。谢谢。
【问题讨论】:
我只是这样写:
if $_ =~ /abc|bcd/ && $_ !~ /diy/
如何在一个正则表达式中编写它。 perl 或 grep 都可以。谢谢。
【问题讨论】:
另一个答案中建议的先行/后行不适用于此问题。并且要使用lookbehind,您需要可变长度的lookbehind,perl 不支持。
/^(?!.*?diy).*?(?:abc|bcd)/s
另一种方法:
/^(?:(?!diy).)*(?:abc|bcd(?!iy))(?:(?!diy).)*\z/s
在任何一种情况下,将 bc 从 |可能会产生更高效的正则表达式。
【讨论】:
当然,这可以通过使用一些前瞻断言的正则表达式实现
$i =~ /^(?=.*(?:abc|bcd))(?!.*diy)/
(?=.*(?:abc|bcd)) 如果有你想要的部分之一,则为真
如果你不想要的字符串在那里,(?!.*diy) 将失败
但我认为你的解决方案更清楚。
【讨论】:
if 非常(非常,非常)然后做一个基准测试。如果您不时这样做,请使用您更喜欢的。
否定一个字符序列通常是正则表达式的痛苦。您必须使用前瞻断言。
如果您正在测试连续序列,您可以尝试使用前瞻和后视来进行测试,例如 (?<!diy)(abc|bcd)(?!diy),但这可能会模棱两可。
我会像你一样离开测试,只丢失默认变量:
if /(abc|bcd)/ and not /diy/
干净整洁。 :)
【讨论】:
$ 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 伴随着失败的终止状态,并表示不匹配。没有输出意味着匹配。
我们使用.*'s 因为匹配是锚定的。 @/RE/ 本身在一行上意味着该行必须匹配正则表达式;即当我们将该行输入到正则表达式机器时,从头到尾,机器处于接受状态。
当你有这样的正则表达式时,在正则表达式中包含搜索语义是不好的。 IE。如果foo 实际上意味着.*(foo).*(匹配文本中的任何地方的foo),这对foo&~bar 来说效果不佳,因为.*(foo&~bar).* 与.*foo.*&~.*bar.* 的含义不同。前者的意思是“匹配任何具有匹配foo&~bar 的子字符串的字符串”。但这是不可能的匹配;任何字符串不能同时为foo 和bar。这是一个空旷的十字路口。但后者的意思是“匹配一个包含foo 的字符串,但在任何地方都不包含bar。”现在你开始做生意了。
【讨论】:
txr,它来自哪里?在我的任何 FreeBSD 或 Linux 机器上,它似乎都不能作为标准工具(端口或包)使用。