【问题标题】:Regex matching string BAR as long as string FOO does not occur before it正则表达式匹配字符串 BAR,只要字符串 FOO 在它之前没有出现
【发布时间】:2019-06-13 17:55:01
【问题描述】:

我正在尝试编写一个正则表达式,它仅适用于包含 BAR 且前面没有 FOO 的字符串。

例如,正则表达式不会匹配:

FOO IS BAR

但是会匹配这个:

BAZ IS BAR

【问题讨论】:

  • 您使用的是什么语言?你执行的命令是什么?您的输入/预期输出是什么?
  • @Rubens 我正在使用 PHP 的 ereg 方法将字符串(系统日志消息)与正则表达式语句进行比较。我不确定这个问题是特定于语言的。
  • 是的。正则表达式的实现因语言而异。这就是为什么正则表达式常见问题解答要求始终用相关语言标记问题。此外,ereg 已被弃用很长时间。
  • @TimPietzcker - 谢谢,我不知道。是的,我同意 ereg 已贬值。这是我不得不使用的内部应用程序。

标签: php regex


【解决方案1】:
(?<!FOO.*)BAR

是正确的正则表达式(但它只适用于 .NET 正则表达式引擎)。

(?&lt;!FOO.*) 是一个negative lookbehind assertion,它断言不可能匹配在当前位置之前包含FOO 的任何字符串。

在 PHP 中,您没有无限的向后看。另一种选择是

^(?:(?!FOO|BAR).)*BAR

说明:

^     # Start of string
(?:   # Match...
 (?!  # (unless the following can be matched here:
  FOO #  either FOO
 |    #  or
  BAR #  BAR)
 )    # (end of lookahead)
 .    # ... any character.
)*    # Repeat as needed
BAR   # Match BAR

但是,即使这也不适用于已弃用的 ereg 函数。您需要preg 函数才能使用环视断言。

但我认为有一种方法适用于ereg

^(FO?|[^FO]|[^O]O)*BAR

说明:

^      # Start of string
(      # Either match:
 FO?   # F or FO
|      # or
 [^FO] # any character except F or O
|      # or
 [^O]O # any non-O character followed by O
)*     # any number of times
BAR    # Then match BAR

但是,如果您的排除字符串比FOO 更复杂,这将很快变得非常复杂...

【讨论】:

  • 你可以让* 不情愿地导致BAR 替代品被安全删除:^(?:(?!FOO).)*?BAR(或者我错过了什么?)
  • 我相信这是答案,但是,我无法让它与我的特定字符串一起使用。 RTMT (FOO) 和 CertExpiry (BAR)。
  • @DanB.:对不起,我又在编辑了——我刚刚发现ereg 甚至不支持惰性量词。也就是说,我认为没有一种方法可以与ereg 一起使用,至少不是在所有情况下。
  • @TimPietzcker 好的,没问题。你在这里提供了很多信息,我相信它会帮助很多人!我会建议我们尽快搬到 preg !谢谢!
  • @DanB.:等等,等等!我想我明白了。请测试它,看看它是否有效。但无论如何,一定要去怀孕!
【解决方案2】:

你可以使用这个正则表达式

^(?=.*BAR)(?!.*?FOO.*?BAR).*$
 --------- --------------
     |           |
     |           |proceed only if there's no FOO before BAR...
     |->proceed only if there's a BAR...CHEERS..

【讨论】:

  • 在使用非.NET语言的情况下,这是一个很好的解决方案。
  • 有一个问题:它将在BAR FOO BAR 上失败(它应该与第一个BAR 匹配)。
【解决方案3】:

您可能会发现将其放入两个正则表达式更容易。例如,如果我们在谈论 Perl,你可以这样做

if ( /BAR/ && !/FOO.*BAR/ )

对我来说,这比试图消极地向后看要清楚得多。

由于您似乎在使用 PHP,我认为 /BAR/ 上的 preg_match 和不匹配 /FOO.*BAR/ 上的另一个没有问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 2013-07-26
    相关资源
    最近更新 更多