正则表达式精确 n OR m 次

问题描述 投票:0回答:7

考虑以下正则表达式,其中

X
any 正则表达式。

X{n}|X{m}

此正则表达式将测试

X
是否出现 完全
n
m
次。

是否有一个正则表达式量词可以测试

X
是否出现
n
m
次?

java php regex
7个回答
123
投票

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

替代方案是:

X{m}(X{k})?

其中

m < n
k
n-m
的值。


107
投票

这里是量词的完整列表(参考。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
  • ...

20
投票

不,不存在这样的量词。但我会将其重组为

/X{m}(X{m-n})?/
以防止 回溯中出现问题


8
投票

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

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

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

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

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


4
投票

TLDR;

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

看起来你想要“x n次”或“x m次”,我认为正则表达式的字面翻译是

(x{n}|x{m}).
像这样https://regex101.com/r/vH7yL5/1

或者,如果您可以拥有超过 m 个“x”的序列(假设 m > n),您可以添加“后面没有“x””和“后面没有“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’”上添加正向前视 (?=) 或在后面添加正向前视 (?<=) on the "no 'x' before", like this: https://regex101.com/r/mC4uX3 /1

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

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


1
投票

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

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

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


0
投票

使用负向后看和负向前看将完全匹配你想要的,不需要捕获组(?

(?

© www.soinside.com 2019 - 2024. All rights reserved.