【问题标题】:Regex to match a string that does not contain 'xxx'正则表达式匹配不包含 'xxx' 的字符串
【发布时间】:2010-09-06 09:11:43
【问题描述】:

我的一个作业问题要求为x,y,z 上不包含xxx 的所有字符串开发一个正则表达式

在阅读了一些内容后,我发现了负前瞻,并使它非常有效:

(x(?!xx)|y|z)*

仍然,本着完整性的精神,是否可以在没有否定前瞻的情况下编写此内容?

阅读我所做的让我认为可以通过carets (^) 的某种组合来完成,但我无法获得正确的组合,所以我不确定。

更进一步,是否可以仅使用 or (|) 运算符排除像 xxx 这样的字符串,但仍以递归方式检查字符串?

2010 年 9 月 6 日编辑:

认为我回答了我自己的问题。我又搞砸了一些,尝试只用 or (|) 语句制作这个正则表达式,我很确定我想通了......它并没有我想象的那么混乱。如果其他人有时间用肉眼验证这一点,我将不胜感激。

(xxy|xxz|xy|xz|y|z)*(xxy|xxz|xx|xy|xz|x|y|z)

【问题讨论】:

  • typoknig - 我已经根据您的最新编辑进一步更新了我的答案。不过,我很感兴趣 - 该模式本质上是我的第一个模式的平面版本。 x{0,2} 可以写成|x|xxa(b|c) 可以写成ab|ac - 为什么你都喜欢第二个?
  • 我实际上更喜欢我的第一个答案,因为它似乎是最直接的,但我的教授是纯粹主义者,我相信他们宁愿看到我只使用最基本的正则表达式元素,我的意思是基本的 (|)(*)

标签: regex


【解决方案1】:

试试这个:

^(x{0,2}(y|z|$))*$

基本思路是这样的:最多匹配2个X,后跟另一个字母或字符串结尾。

当您达到 3 个 X 的点时,正则表达式没有允许它继续匹配的规则,它会失败。

工作示例:http://rubular.com/r/ePH0fHlZxL

一种不太紧凑的写法是(带有可用空格,通常是/x 标志):

^(
y|         # y is ok
z|         # so is z
x(y|z|$)|  # a single x, not followed by x
xx(y|z|$)  # 2 x's, not followed by x
)*$

根据最新的编辑,这里有一个更扁平的模式版本:我不完全确定我理解你对管道的迷恋,但你可以消除更多的选择 - 通过允许你的第二组空匹配不需要重复第一组的排列。该正则表达式还允许 ε,我认为它包含在您的语言中。

^(xxy|xxz|xy|xz|y|z)*(xx|x|)$

【讨论】:

  • @typoknig - 我发布了一种更直接的方式来匹配您的语言。它们之间还有很多,比如^(x|y|xx?(y|z|$))*$
【解决方案2】:

基本上你已经有了正确的答案——干得好。 :)

[^abc] 集合中的克拉 (^) 只会匹配在该集合中找不到字符的位置,因此它用于匹配字符顺序(即字符串)的应用程序是有限且弱的。

Regex 有数字量词 {n}{a,b},它们允许您匹配定义的模式重复次数,这适用于该特定模式(因为它是重复的“x”),但它并不能特别表达您试图解决的问题(即使是正则表达式!)并且有点脆弱(例如,它不适合负匹配 'xyx'。

一个或模式再一次会很冗长而且相当不具表现力,但它可以作为片段来完成:

(x|xx)[^x] // x OR xx followed by NOT x

显然,您可以使用迭代算法来做到这一点,但与正则表达式相比效率非常低。

尽管超越解决方案的思考做得很好。

【讨论】:

  • (x|xx)[^x] 将在字符串末尾失败。
  • @Tim Pietzcker - 当然它只是一个片段,它会随着上下文而变化 @typoknig - 荒谬的是,任何模式都可以表示为一系列 OR,您只需将每个绝对可能的匹配 OR 在一起,就是这样到那时,它不再是您所代表的模式。但假设是的,它总是有可能的。
【解决方案3】:

我知道您不想使用前瞻,但这是解决此问题的另一种方法:

^(?:(?!xxx)[xyz])*$

将匹配任何字符行 xyz,只要它不包含字符串 xxx

【讨论】:

  • 非常好,肯定有很多选择。我曾经在这里遇到过一个问题(但我现在找不到),有人问我一个类似的问题,因为消极的前瞻不适用于他们的编译器或类似的东西。听起来对吗?
  • 通常缺少 lookbehind (最值得注意的例子是 JavaScript 和 Ruby,直到 1.8);如今,除了 POSIX/GNU BRE/ERE 引擎之外,大多数正则表达式风格都具有前瞻性。
猜你喜欢
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
  • 2015-02-26
  • 2021-11-13
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多