【问题标题】:Regular Expression Opposite正则表达式相反
【发布时间】:2010-10-25 10:53:54
【问题描述】:

是否可以编写一个正则表达式来返回所需结果的反函数?正则表达式通常具有包容性 - 查找匹配项。我希望能够将正则表达式转换为相反的 - 断言没有匹配项。这可能吗?如果有,怎么做?

http://zijab.blogspot.com/2008/09/finding-opposite-of-regular-expression.html 声明你应该用

括起你的正则表达式
/^((?!^ MYREGEX ).)*$/

,但这似乎不起作用。如果我有正则表达式

/[a|b]./

,字符串“abc”使用我的正则表达式和 zijab 建议的相反返回 false,

/^((?!^[a|b].).)*$/

。是否可以写一个正则表达式的逆,还是我想错了?

【问题讨论】:

  • 您使用的是哪个正则表达式包(您使用的是哪种语言)?如果您的正则表达式包不支持相当现代的 PCRE(与 Perl 兼容的正则表达式)包,则可能只是误解了 Zijab 的示例(零宽度负前瞻)。

标签: regex


【解决方案1】:

您不能检查一下是否没有匹配项吗?我不知道你用的是什么语言,但是这个伪代码怎么样?

if (!'Some String'.match(someRegularExpression))
    // do something...

如果您只能更改正则表达式,那么您从链接中获得的那个应该可以工作:

/^((?!REGULAR_EXPRESSION_HERE).)*$/

【讨论】:

  • 嗯,这就是问题所在。我不是在写正则表达式或代码。我有一个应用程序可以让人们输入他们自己的正则表达式,并且它们需要具有包容性或排他性。我要么需要他们输入另一条数据 - 包含/独占,要么强制他们使用“相反”模式(如果存在)将它们全部写入包含或独占。这只会被程序员使用,所以复杂性不是问题 - 只是可能性。
  • 嗯,我明白了。那为什么这不起作用? /^((?!REGULAR_EXPRESSION_HERE).)*$/ (取自您的链接。)它对我有用。
【解决方案2】:

您的反向正则表达式不起作用的原因是因为负前瞻中的“^”:

/^((?!^[ab].).)*$/
      ^            # WRONG

也许它在 vim 中有所不同,但在我熟悉的每种正则表达式风格中,插入符号匹配字符串的开头(或多行模式下的行开头)。但我认为这只是博客条目中的一个错字。

您还需要考虑您正在使用的正则表达式工具的语义。例如,在 Perl 中,这是真的:

"abc" =~ /[ab]./

但在 Java 中,这不是:

"abc".matches("[ab].")

这是因为传递给matches() 方法的正则表达式隐式锚定在两端(即/^[ab].$/)。

采用更常见的 Perl 语义,/[ab]./ 表示目标字符串包含一个由 'a' 或 'b' 后跟至少一个(非行分隔符)字符组成的序列。换句话说,在任何时候,条件都是 TRUE。该语句的反面是,在每一点条件都是 FALSE。这意味着,在您使用每个字符之前,您执行一个否定的前瞻来确认该字符不是匹配序列的开始:

(?![ab].).

而且您必须检查 每个 字符,因此正则表达式必须在两端锚定:

/^(?:(?![ab].).)*$/

这是一般的想法,但我认为不可能反转 每个 正则表达式 - 当原始正则表达式可以包括正面和负面的环视、不情愿和所有格量词以及谁知道时-什么。

【讨论】:

    【解决方案3】:

    您可以通过在开头写入^ ([^…]) 来反转字符集。所以[ab] 的相反表达式(匹配ab)是[^ab](既不匹配a 也不匹配b)。

    但是你的表达越复杂,互补的表达也就越复杂。一个例子:

    您想匹配文字 foo。一个表达式,除了包含 foo 的字符串之外,它必须匹配任何其他内容

    1. 任何短于foo (^.{0,2}$) 的字符串,或
    2. foo (^([^f]..|f[^o].|fo[^o])$) 的任意三个字符的长字符串,或
    3. 任何不包含foo的字符串。

    所有这些都可以工作:

    ^[^fo]*(f+($|[^o]|o($|[^fo]*)))*$
    

    但请注意:这仅适用于foo

    【讨论】:

      【解决方案4】:

      您也可以通过使用re.split 来执行此操作(在python 中),并根据您的正则表达式进行拆分,从而返回所有与正则表达式不匹配的部分how to find the converse of a regex

      【讨论】:

        【解决方案5】:

        在 perl 中,您可以使用 $string !~ /regex/; 进行反匹配。

        【讨论】:

          【解决方案6】:

          借助 grep,您可以使用 --invert-match-v

          【讨论】:

            【解决方案7】:

            Java 正则表达式有一种有趣的方法(可以测试here),您可以在其中为您想要的字符串创建一个贪婪的可选匹配,然后匹配它后面的数据。如果贪婪匹配失败,它是可选的,所以没关系,如果它成功,它需要一些额外的数据来匹配第二个表达式,所以失败。

            它看起来违反直觉,但确实有效。

            例如,(foo)?+.+ 匹配 barfooxxfoo,但不会匹配 foo(或空字符串)。

            这在其他方言中可能是可能的,但我自己无法让它发挥作用(如果第二次匹配失败,他们似乎更愿意回溯?)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-08-21
              • 2015-01-20
              相关资源
              最近更新 更多