使用正则表达式匹配由b分隔的a。

3

我已经尝试了一段时间来匹配以下情况,但我不太擅长正则表达式,希望能得到一些帮助...

我需要匹配所有包含a或b的单词,但每个a都需要由b分隔开,因此任何单词中都不应出现aa。

接受的单词:a、b、ba、ababbaba
不接受的单词:aa、babaa


纯属好奇,有没有人可以发一个“公正”的解决方案,不需要使用向前搜索? - georg
我有一个带有前瞻的解决方案,但主要是在尝试弄清楚如何在没有em的情况下完成它...所以thg沿着正确的道路前进,只是我无法理解它。 - mrhn
4个回答

4
使用锚定的负预测:
^(?!.*aa)[ab]+$

[ab]+ 表示字符串由 a 和 b 组成(非常直观)。

(?!.*aa) 这个表达式用 ^ 锚定在开头,表示输入中没有 "aa" 出现。


不使用前瞻的解决方法:

^(b|ab|a$)+$

通过左到右的顺序, 一起使用的术语 or 将按顺序执行。有了这个想法,正则表达式的工作方式应该很明显。

实时演示中查看此正则表达式的工作方式。


你可能想要添加 $ - georg
@thg435 嗯,好主意。完成了。 - Bohemian
这已经接近我想要的了,至少现在它解决了问题,但是让问题保持开放状态,看看是否有人可以在没有预先查看的情况下解决它,否则今晚我就关闭它。 - mrhn
@raaba,请查看已编辑的答案,以获取无前瞻解决方案。 - Bohemian
第二个表达式真是一颗珍宝。非常感谢! - georg

3
/^a?(ba?)*$/

请提供需要翻译的文本。
/^         # start regex and start of string
a?         # optional a
(          # start group
  b        # exactly one b
  a?       # optional a
)*         # end group, and repeat zero or more times
$/         # end regex and end of string

简单来说,第一个字符可以是 a,或者直接进入主要重复组,该组可以重复零次或多次,并匹配一个后面跟着零个或一个 ab,直到结尾。

第二种方法

(根据评论避免灾难性回溯)

/^a?(b|ba)*$/

解释...

/^         # start regex and start of string
a?         # optional a
(          # start group
  b|ba     # match `b` or `ba`
)*         # end group, and repeat zero or more times
$/         # end regex and end of string

简单来说,第一个字符是a,或者进入主要的重复组,该组可以重复零次或多次,并且由bba中的一个组成,然后结束匹配和正则表达式。


2
+1,尽管我不喜欢(b+a?)*中的? - 它可能会导致灾难性回溯。更好的方法是:/^a?(b+a)*b*$/ - Bergi
1
或者怎么样... /^a?(b|ba)*$/ - Billy Moon
当您在 b 后面删除了 +,它已经没问题了... 不确定 b|ba,重复的 b 可能不是最佳选择。 - Bergi

2

理想的正则表达式如下:

^a?(b+a)*b*$

关键在于这是一个简单的正则表达式,可以在一次扫描中匹配或拒绝,没有回溯。


粗体语句 - “理想的正则表达式”。难道没有改进的空间吗?与“/^a?(b|ba)*$/”相比,它更理想在哪里? - Billy Moon
@Billy 大胆的陈述总是有帮助的! :-D 你的正则表达式可以改为 /^a?(ba?)*$/。无论如何,在这个阶段选择它们之间的唯一方法是查看生成的NFA和DFA的状态图,而我宁愿过自己的生活。 (自动机状态图是我最不喜欢的事情之一,特别是当它们以某种奇怪的内部形式编码时。) - Donal Fellows

0

检查一下这个对你是否有效。 \b((a?b+a?)+)\b|\b((a?b+)+)\b|\b(((b+a?)*)\b)

我没有时间验证每种可能的情况。

你可以使用这个在线正则表达式在线验证器

祝好


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