134

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

X{n}|X{m}

此正则表达式将测试X发生的确切 n时间或m时间。

是否有一个正则表达式量词可以X准确地测试某个事件nm时间?

4

6 回答 6

107

没有一个量词表示“正好 m 或 n 次”。你这样做的方式很好。

另一种选择是:

X{m}(X{k})?

其中m < nk是 的值n-m

于 2012-12-14T08:10:58.373 回答
90

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

  • ?, ??- 0 或 1 次出现(??懒惰,?贪婪)
  • *, *?- 任意数量的出现
  • +, +?- 至少出现一次
  • {n}- 确切地n发生
  • {n,m}-n发生m,包容
  • {n,m}?-n发生m,懒惰
  • {n,}, {n,}?- 至少n发生

要获得“恰好 N 或 M”,您需要编写两次量化的正则表达式,除非 m,n 是特殊的:

  • X{n,m}如果m = n+1
  • (?:X{n}){1,2}如果m = 2n
  • ...
于 2012-12-14T08:16:33.803 回答
19

不,没有这样的量词。但我会对其进行重组/X{m}(X{m-n})?/以防止回溯中出现问题

于 2012-12-14T08:12:45.900 回答
4

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

看起来你想要“xn 次”或“xm 次”,我认为正则表达式的直译是(x{n}|x{m}). 这样的https://regex101.com/r/vH7yL5/1

或者,如果您可以拥有超过 m 个“x”的序列(假设 m > n),您可以添加 'following no "x"' 和 'followed 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

最后,为了匹配一个字符的远距离匹配,您可以在“no 'x' after”上添加正向向前看 (?=) 或在“no 'x' before”上添加正向向后看 (?<=),像这样:https ://regex101.com/r/mC4uX3/1

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

这样,您将只匹配您想要的确切数量的“x”。

于 2016-07-07T16:03:10.090 回答
4

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

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

这将找到所有出现的十六进制颜色代码(它们的长度为 3 位或 6 位)。但是当我像这样翻转它时

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

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

于 2019-01-23T14:02:47.013 回答
1

看看 Enhardened 的回答,他们说倒数第二个表达式不会匹配它们之间只有一个字符的序列。有一种简单的方法可以在不使用前瞻/后视的情况下解决此问题,那就是将开始/结束字符替换为边界字符。这使您可以匹配包括开始/结束在内的单词边界。因此,适当的表达应该是:

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

正如您在此处看到的:https ://regex101.com/r/oC5oJ4/2 。

于 2018-05-08T12:13:23.427 回答