正则表达式在.NET中重复的字符和长度

时间:2018-05-02 03:01:43

标签: c# .net regex regex-group

我有一个正则表达式,我需要匹配捕获中的字母部分。这些字母的长度可以是1-3个字符,并且必须是相同的字母。没有ABC,但A,AA或AAA工作,后跟一个数字。我目前只能匹配A1,而不是AA1。我正在使用.NET作为Regex。

^(?<pool>([A-Z])\1{0,2})(?<number>(100)|[1-9]\d?)$

A1
AA2
AAA3
B5
CC7

2 个答案:

答案 0 :(得分:4)

以下正则表达式适合您吗?

\b(([A-Z])\2{0,2}(?:100|[1-9]\d?))\b

DEMO

确实接受:A1 AA2 AAA3 B5 CC7且不符合AAAA4ABC123

如果您想使用命名捕获组和反向引用,那么您可以将正则表达式更改为:

^(?<pool>([A-Z]))\k<pool>{0,2}(?<number>(100|[1-9]\d?))$

DEMO

让我知道它是否适合你,也看看:

https://www.regular-expressions.info/named.html

最后但并非最不重要的是,如果您希望指定的捕获组<pool>匹配并捕获AAAAAA,您可以使用:

^(?<pool>([A-Z])\2{0,2})(?<number>(100|[1-9]\d?))$

DEMO

只有名为捕获组:

^(?<pool>(?<letter>[A-Z])\k<letter>{0,2})(?<number>(100|[1-9]\d?))$

DEMO

答案 1 :(得分:2)

Allan的一个小补充和纠正的答案:

第三种模式在.NET的正则表达式引擎中不能正确匹配,因为反向引用\2的编号必须与显示的PCRE模式不同(使用regex101)。

而不是\2,而不是\1

^(?<pool>([A-Z])\1{0,2})(?<number>(100|[1-9]\d?))$

这个dotnetfiddle演示了这个问题:我只生成了前100个(来自A1-A100)的约300个测试用例。

您可以使用.NET正则表达式测试程序regexstorm自行检查。

为什么呢?在.NET regex和PCRE中如何引用与常规捕获组混合的命名捕获组之间存在细微差别,例如:用PHP。

乍一看它的工作方式相同:

  

使用括号的捕获从左到右自动编号   正确的基于开头括号的顺序   表达,从一个**开始。编号为零的捕获是   文本与整个正则表达式模式匹配。

参考。 MSDN: Grouping Constructs in Regular Expressions

所以,而

  

大多数口味都包括命名和未命名的捕获组   从左到右计算它们的开括号。添加命名   将组捕获到现有的正则表达式仍然会扰乱数据   未命名的群体

然而,在.NET中,

  

未命名的捕获组是   首先分配数字,从左边算出它们的左括号   向右,跳过所有命名组。之后,命名组是   通过计算左括号来分配后面的数字   从左到右的命名组。

这实际上是在答案中链接的regular-expressions.info/named.html上的同一页上解释的。

一个简单的例子:

要在.NET中匹配1a1,您可以使用

(?<named>(\d)a)\1

要在PHP中以类似的方式匹配,您必须使用\ 2而不是

(?<named>(\d)a)\2

道德:

  

建议不要混用命名和编号的捕获组,因为   风味与群体的编号方式不一致。

BTW:

我已经准备好了这种模式\b(?<pool>([A-Z])\1{0,2})(?<number>(\d{1,2}(?!\d)|100))\b,但随后将注意力转移到了上面提到的差异上。您还可以在链接演示中使用\1 vs \2