正则表达式正好 n 或 m 次

考虑下面的正则表达式,其中 X任何正则表达式。

X{n}|X{m}

该正则表达式将测试 X发生 没错 nm的次数。

是否有一个正则表达式量词可以精确地测试出现 Xnm次?

126635 次浏览

没有一个单一的量词表示“精确的 m 或 n 次”。你做这件事的方式是好的。

另一种选择是:

X{m}(X{k})?

其中 m < nkn-m的值。

没有,没有这样的量词。但是我会把它改成 /X{m}(X{m-n})?/,以防 回溯问题

下面是完整的量词列表(参考文献 http://www.regular-expressions.info/reference.html) :

  • 出现 ???-0或1次(??是懒惰的,?是贪婪的)
  • **?-任意数量的事件
  • ++?-至少一次
  • {n}-正好出现 n
  • {n,m}-nm出现,包括
  • {n,m}?-nm发生,懒惰
  • {n,}{n,}?-至少发生 n

为了得到“精确的 N 或 M”,你需要写两次量化的正则表达式,除非 m,n 是特殊的:

  • 如果是 m = n+1
  • 如果是 m = 2n
  • ...

(?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

看起来你想要“ x n 乘以”或者“ x m 乘以”,我认为 regex 的直译应该是 (x{n}|x{m}). 像这样的 https://regex101.com/r/vh7yl5/1

或者,在你可以有一个超过 m“ x”的序列(假设 m > n)的情况下,你可以加上“ follow no“ x”和“ follow by no“ x”,翻译成 [^x](x{n}|x{m})[^x],但是这会假设在你的“ x”后面和后面总是有一个字符。正如你在这里看到的: https://regex101.com/r/bB2vH2/1

你可以把它改成 (?:[^x]|^)(x{n}|x{m})(?:[^x]|$),翻译成“后面没有‘ x’或者后面有行开始”和“后面没有‘ x’或者后面有行结束”。但是,它仍然不会匹配两个序列,它们之间只有一个字符(因为第一次匹配之后需要一个字符,第二次匹配之前需要一个字符) ,正如您在这里看到的: https://regex101.com/r/oC5oJ4/1

最后,为了匹配一个字符的远距离匹配,您可以添加一个积极的前瞻(?=)在“后面没有‘ x’”或者在后面有积极的表情(?< =)在“ no‘ x’before”上,像这样: https://regex101.com/r/mC4uX3/1

(?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

这样你将只匹配你想要的‘ x’的确切数目。

看一下 Enharded 的答案,他们声明他们的倒数第二个表达式不会只匹配一个字符之间的序列。有一种简单的方法可以解决这个问题,而不需要使用“向前看/向后看”,那就是用边界字符替换开始/结束字符。这使您可以匹配包括 start/end 的单词边界。因此,恰当的表达方式应该是:

(?:[^x]|\b)(x{n}|x{m})(?:[^x]|\b)

正如你在这里看到的: https://regex101.com/r/oC5oJ4/2

非常老的帖子,但我想贡献一些可能有帮助的东西。 我已经按照问题中陈述的方式进行了尝试,它确实有效,但有一个问题: 数量的顺序很重要,考虑一下:

#[a-f0-9]{6}|#[a-f0-9]{3}

这将发现所有出现的十六进制颜色代码(它们是3或6位长)。但是当我像这样把它翻过来

#[a-f0-9]{3}|#[a-f0-9]{6}

它只会找到3位数字的或6位数字的前3位数字。这确实有意义,正则表达式专家可能会立即发现这一点,但对于许多人来说,这可能是一种奇怪的行为。不管顺序如何,有一些高级的正则表达式特性可以避免这种陷阱,但并不是每个人都深入了解正则表达式模式。