简化正则表达式 "ab|a|b"

3
以下正则表达式应如何简化:

以下正则表达式应如何简化:

ab|a|b

我希望您能给我一个更简洁的版本,即只有一个a和一个b,是否可能?

一些尝试:

a?b?       # matches empty string while shouldn't
ab?|b      # still two b

请注意,实际的正则表达式具有更复杂的ab部分,即不是单个字符,而是内部子正则表达式。

我的直觉告诉我它不能被简化。 - Sam I am says Reinstate Monica
你需要简化这个正则表达式吗?虽然有一些冗余,但它仍然非常简单易读。 - Jeff
1
@leppie:这匹配了aa和bb,它们都是无效的。 - Jeff
@Jeff 你说的没错,这个示例确实很易读,但是真正的正则表达式有更复杂的ab部分。 - sp00m
@m.buettner,假设是Java的一个问题,但这更像是一个通用正则表达式问题,即让我们考虑一种支持每个正则表达式子句的语言(不像JavaScript的语言)。 - sp00m
显示剩余6条评论
1个回答

6

如果你正在使用Perl或一些PCRE引擎(比如PHP的preg_函数),你可以像这样在模式中引用先前的组:

/(a)(b)|(?1)|(?2)/

这个功能的主要目的是支持递归,但也可以用于模式重用。
请注意,在这种情况下,您无法避免在第一个交替中捕获a和b,这会导致一些(可能)不必要的开销。为了避免这种情况,您可以在从未执行的条件内定义组。这样做的规范方式是使用(?(DEFINE)...)组(它检查命名的DEFINE组是否匹配任何内容,但是当然该组不存在):
/(?(DEFINE)(a)(b))(?1)(?2)|(?1)|(?2)/

如果您的引擎不支持这个功能(编辑:由于您正在使用Java,因此不支持此功能),那么在单个模式中,您最好能得到的就是。
ab?|b

或者,您可以通过字符串连接/格式化手动构建ab|a|b版本,例如:

String a = "a";
String b = "b";
String pattern = a + b + "|" + a + "|" + b;

这也避免了重复。或者,您可以针对主题字符串使用三个单独的模式abab(其中第一个再次是后两个的连接)。


1
@leppie 我认为这是主观的,如果你这样做,你应该使用 (?:ab?) - 否则括号会通过捕获 ab 增加不必要的开销(也许我应该将其添加到第一个解决方案中)。 - Martin Ender
1
+1 正则表达式:即使是 40 年后,你每天都会学到新东西;p - leppie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接