考虑以下正则表达式,其中X
是任何正则表达式。
X{n}|X{m}
此正则表达式将测试X
发生的确切 n
时间或m
时间。
是否有一个正则表达式量词可以X
准确地测试某个事件n
或m
时间?
没有一个量词表示“正好 m 或 n 次”。你这样做的方式很好。
另一种选择是:
X{m}(X{k})?
其中m < n
和k
是 的值n-m
。
这是量词的完整列表(参考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
不,没有这样的量词。但我会对其进行重组/X{m}(X{m-n})?/
以防止回溯中出现问题。
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”。
很老的帖子,但我想贡献一些可能会有所帮助的东西。我已经完全按照问题中所述的方式进行了尝试,它确实有效,但有一个问题:数量的顺序很重要。考虑一下:
#[a-f0-9]{6}|#[a-f0-9]{3}
这将找到所有出现的十六进制颜色代码(它们的长度为 3 位或 6 位)。但是当我像这样翻转它时
#[a-f0-9]{3}|#[a-f0-9]{6}
它只会找到 3 位数字或 6 位数字的前 3 位数字。这确实是有道理的,Regex 专业人士可能会立即发现这一点,但对于许多人来说,这可能是一种特殊的行为。有一些高级的正则表达式功能可以避免这个陷阱,不管顺序如何,但并不是每个人都深入了解正则表达式模式。
看看 Enhardened 的回答,他们说倒数第二个表达式不会匹配它们之间只有一个字符的序列。有一种简单的方法可以在不使用前瞻/后视的情况下解决此问题,那就是将开始/结束字符替换为边界字符。这使您可以匹配包括开始/结束在内的单词边界。因此,适当的表达应该是:
(?:[^x]|\b)(x{n}|x{m})(?:[^x]|\b)
正如您在此处看到的:https ://regex101.com/r/oC5oJ4/2 。