匹配出现两次或四次数字的正则表达式。

128

这是一个关于正则表达式的简单问题,但我找不到答案。

我想确定一个数字是否恰好出现 两次四次。我可以使用什么语法?

\d{填什么?}

我尝试过\d{2,4},但这个表达式也接受三个数字。


1
例如,匹配两位或四位的年份。 - DavidRR
如果字符串是abc 123 xyz,您希望发生什么?它应该匹配12,因为这是恰好连续两个数字吗?还是不应该,因为12是更大的数字序列123的一部分,而123本身既不是2位也不是4位长?如果我必须猜测,我认为您想要后者的行为,但从您的问题中并不清楚。示例和/或更清晰的规范将有所帮助。 对于abc 12345 def的同样问题...那里应该发生什么? - Jean-François Corbett
2个回答

195

没有特定的语法,但有很多方法可以做到:

(?:\d{4}|\d{2})    <-- alternation: four digits if possible, else just two
\d{2}(?:\d{2})?    <-- two digits, plus two more if possible
(?:\d{2}){1,2}     <-- two digits, times one or two

例如,要匹配由一个或多个字母 A-Z 后跟两个或四个数字的字符串,可以编写^[A-Z]+(?:\d{4}|\d{2})$;要匹配由逗号分隔的两或四位数字列表,可以编写 ^((?:\d{4},|\d{2},)*(?:\d{4}|\d{2})$^(?:\d{2}(?:\d{2})?,)*\d{2}(?:\d{2})$


2
个人而言,我一开始就想到了\d{2}(?:\d{2})?这个解决方案 - 这些方案的变化很好 - 特别是最后一个,看起来非常好且可扩展。 - Nightfirecat
3
对于使用替换匹配4位数字和2位数字时,注意顺序是值得肯定的。此外,提供其他变体也做得很好。 - Ahmad Mageed
10
对于像我一样不理解 (?: 的用法的人,它是用来开始一个"非捕获组"(不打算在替换语句中引用的组)。你也可以只使用圆括号,但这会创建一个捕获组。更多细节请参见这里:https://dev59.com/QXA75IYBdhLWcg3wBkS1 - Jeremy Moritz
这将对“333”和“33”显示相同的结果。 - Dan
1
@Dan:这些正则表达式匹配完整的字符串“333”。你可能错误地使用了正则表达式库的“查找匹配子字符串”功能,而不是其“检查完整字符串是否匹配”的功能。你应该查阅其文档。 - ruakh
显示剩余10条评论

21
(?<!\d)(\d{2}|\d{4})(?!\d)

这是正确的做法。被接受的答案是错误的。

它将匹配3位数(或5位数)。所以在我看来是错的

  1. 检查在2位数或4位数序列之前是否没有数字,或在两个或四个数字序列之后是否没有数字。
  • (?<!)语法是负向回顾。

  • (?!)语法是负向前瞻。

上述方法适用于字符串的中间位置:

如果您的搜索字符串周围没有内容,您可以使用^$作为字符串的开头和结尾锚点:

^\d{4}$|^\d{2}$

4
我不会说被接受的答案是错的。我想说的是,问题不太清楚,而那个答案解决了其中一个有效的解释。你的回答解决了另一个有效的解释(我碰巧认为这是一个更可能的解释 - 但显然问问题的人并不这样认为...)。 - Jean-François Corbett
7
“它将匹配3个数字”并不是很准确。我认为您的意思是“它将匹配一个3位数序列中的2位数字子序列”。 - Jean-François Corbett
2
另外,您的答案在5位或更多位数字序列上效果不如预期。我不是正则表达式专家,但我想修复它的一种方法是使否定前瞻/后瞻应用于两种情况(2位和4位数字序列):(?<!\d)(\d{2}|\d{4})(?!\d) - Jean-François Corbett
我认为你关于5位数字的说法是正确的。谢谢你的纠正。我会进行修正。 - JGFMK
1
@Jean-FrançoisCorbett - 问问题的人明确表示... "但是这个表达式也接受三位数字"。所以我坚持认为答案是错误的。它并没有解决这个问题。 - JGFMK
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接