【问题标题】:How to write a regex that includes `abc` or `bcd` but not `diy` in one line如何在一行中编写包含`abc`或`bcd`但不包含`diy`的正则表达式
【发布时间】:2012-03-28 02:40:44
【问题描述】:

我只是这样写:

if $_ =~ /abc|bcd/ && $_ !~ /diy/

如何在一个正则表达式中编写它。 perlgrep 都可以。谢谢。

【问题讨论】:

    标签: regex perl shell


    【解决方案1】:

    另一个答案中建议的先行/后行不适用于此问题。并且要使用lookbehind,您需要可变长度的lookbehind,perl 不支持。

    /^(?!.*?diy).*?(?:abc|bcd)/s
    

    另一种方法:

    /^(?:(?!diy).)*(?:abc|bcd(?!iy))(?:(?!diy).)*\z/s
    

    在任何一种情况下,将 bc 从 |可能会产生更高效的正则表达式。

    【讨论】:

      【解决方案2】:

      当然,这可以通过使用一些前瞻断言的正则表达式实现

      $i =~ /^(?=.*(?:abc|bcd))(?!.*diy)/
      

      (?=.*(?:abc|bcd)) 如果有你想要的部分之一,则为真

      如果你不想要的字符串在那里,(?!.*diy) 将失败

      但我认为你的解决方案更清楚。

      【讨论】:

      • 在这种情况下,一个正则表达式会比两个正则表达式快吗?
      • @madper 抱歉,但我认为在这种情况下,关于性能的每个答案都是一个疯狂的猜测。如果你经常这样做if 非常(非常,非常)然后做一个基准测试。如果您不时这样做,请使用您更喜欢的。
      【解决方案3】:

      否定一个字符序列通常是正则表达式的痛苦。您必须使用前瞻断言。

      如果您正在测试连续序列,您可以尝试使用前瞻和后视来进行测试,例如 (?<!diy)(abc|bcd)(?!diy),但这可能会模棱两可。

      我会像你一样离开测试,只丢失默认变量:

      if /(abc|bcd)/ and not /diy/
      

      干净整洁。 :)

      【讨论】:

      • 如果您在正则表达式中没有支持,则必须使用前瞻运算符;但是否定肯定是在有限自动机的范围内。如果你要建表,会有很多状态,但没有它是可能的;例如代数。您可以执行从 regex 公式到 regex 公式的推导,而不是从一个气泡到另一个气泡。
      【解决方案4】:
      $ 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 的子字符串的字符串”。但这是不可能的匹配;任何字符串不能同时为foobar。这是一个空旷的十字路口。但后者的意思是“匹配一个包含foo 的字符串,但在任何地方都不包含bar。”现在你开始做生意了。

      【讨论】:

      • 什么是txr,它来自哪里?在我的任何 FreeBSD 或 Linux 机器上,它似乎都不能作为标准工具(端口或包)使用。
      • 这是新的(nongnu.org/txr。
      • 非常有趣。如果您不反对,我可能会将它添加到 FreeBSD 端口树中。
      • 我会很高兴;即使是最轻微的移植困难,也请不要害羞。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 2010-12-20
      • 2022-07-21
      相关资源
      最近更新 更多