正则表达式的反义匹配

18 浏览
0 Comments

正则表达式的反义匹配

是否有可能编写一个返回相反结果的正则表达式?正则表达式通常是包容性的,即找到匹配项。我想能够将一个正则表达式转换为它的相反形式,即断言没有匹配项。这可能吗?如果是,如何实现?

http://zijab.blogspot.com/2008/09/finding-opposite-of-regular-expression.html中提到,你应该使用括号将正则表达式包裹起来,

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

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

/[a|b]./

那么字符串"abc"在我的正则表达式和zijab建议的相反形式

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

下都返回false。是否可能编写正则表达式的相反形式,或者我思考得不正确?

0
0 Comments

正则表达式的反义可以通过在开头写一个^来实现([^…])。因此,[ab](匹配a或b)的反义表达式是[^ab](不匹配a和b)。

但是,表达式变得越复杂,互补表达式也变得越复杂。一个例子:

您想匹配字面上的foo。一个与不包含字符串foo的字符串匹配的表达式必须匹配以下任一条件:

  1. 任何长度小于foo的字符串(^.{0,2}$),或者
  2. 任何长度为三个字符但不是foo的字符串(^([^f]..|f[^o].|fo[^o])$),或者
  3. 不包含foo的任何更长的字符串。

整体而言,这可能有效:

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

但请注意:这仅适用于foo。

0
0 Comments

正则表达式取反(Regular Expression Opposite)问题的原因是由于否定预查中的“^”符号:

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

^ # 错误

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

您还需要考虑您使用的正则表达式工具的语义。例如,在Perl中,以下语句成立:

"abc" =~ /[ab]./

但在Java中,这个语句不成立:

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

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

按照更常见的Perl语义,/[ab]./意味着目标字符串包含一个由'a'或'b'开头,后跟至少一个(非行分隔符)字符的序列。换句话说,在任何点上,条件都是TRUE。这个语句的否定是,在每一个点上,条件都是FALSE。这意味着,在消耗每个字符之前,您执行一个否定预查来确认该字符不是匹配序列的开头:

(?![ab].).

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

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

这是一般的想法,但我认为不可能取反每个正则表达式——尤其是当原始的正则表达式可以包括正向和负向预查、勉强和占有量词以及其他各种功能时。

0
0 Comments

问题的出现原因是因为作者正在开发一个应用程序,该应用程序允许用户输入正则表达式,并且需要根据用户输入的正则表达式来确定它是包含还是排除的。作者希望找到一种方法,让用户能够通过输入的正则表达式,自动得到对应的相反正则表达式。

解决方法是通过使用否定预查的方式来构建相反的正则表达式。作者提供了一个示例的正则表达式:/^((?!REGULAR_EXPRESSION_HERE).)*$/,它能够匹配除了包含"REGULAR_EXPRESSION_HERE"的任何字符串之外的所有字符串。

还有另一个解决方法的思路,就是让用户输入一个额外的数据来指示是包含还是排除的,或者强制用户使用相反的模式来编写正则表达式。这样做的话,用户只需要提供一个正则表达式,而不需要提供相反的正则表达式。

总结起来,作者提出了两个解决方法:一种是通过使用否定预查构建相反的正则表达式,另一种是让用户提供额外的数据或使用相反的模式来编写正则表达式。这些解决方法可以帮助作者解决用户输入正则表达式的包含或排除需求。

0