在正则表达式中匹配逗号分隔的组(模式中没有冗余)



>我有一个正则表达式,它匹配表示Excel范围的字符串(加上单个单元格)

^[A-Z]+[1-9][0-9]*(:[A-Z]+[1-9][0-9]*)?(,[A-Z]+[1-9][0-9]*(:[A-Z]+[1-9][0-9]*)?)*$

例如,它匹配以下字符串:

C5:H6,J5:P6,R5:DM6,C15

我问是否有任何方法可以避免模式中的冗余:

C6[A-Z]+[1-9][0-9]*匹配,但也H6由相同的模式匹配。

同样,J6:P6C6:H6匹配的相同模式匹配。

如果要表达类似"匹配此模式 1 次,或 * 次,但仅在逗号分隔的情况下"之类的内容。

提前感谢!

您可以按如下方式更改正则表达式:

^([A-Z]+[1-9][0-9]*(:[A-Z]+[1-9][0-9]*)?(,(?!$)|$))*$

关键的变化是末尾的这个子表达式:

(,(?!$)|$)

它匹配可选的逗号字符,除非它位于匹配的末尾,在这种情况下,不得有其他字符。这会阻止您匹配以悬挂逗号结尾的序列。

这是关于 ideone 的相应演示。

对于任何系列的范围和单个单元格,请使用正则表达式模式

(?!,)(?:(?:^|,)[A-Z]+(?!0)[0-9]+(?::[A-Z]+(?!0)[0-9]+)?)+

或者,如果您只想匹配以逗号分隔的一系列相同范围(或单个单元格),则

^([A-Z]+(?!0)[0-9]+(?::[A-Z]+(?!0)[0-9]+)?)(,1)*

要删除源代码中的冗余,您可以将重复的组件存储到字符串变量中,并从字符串中构造正则表达式。

像这样:

string cellname = "[A-Z]+[1-9][0-9]*";
string cellrange = cellname + "(:" + cellname + ")?";
Regex pattern = new Regex("^" + cellrange + "(," + cellrange + ")*$")

如果您询问是否有用于分隔符的二进制正则表达式运算符,即您可以为其编写的内容

A op B

并有意为

A(BA)*

那么恐怕这样的事情并不存在。附录:但是,您可以接近

((^|B)A)+$

这转换为"一个或多个以字符串开头或 B 为前缀的 As"。 在这里,您的 B 将是逗号,您的 As 将是范围。 然后,您可以在范围内使用相同的技术来用冒号分隔单元格。 但是,您将使用(xxx|:)而不是(^|,),其中xxx扮演单元格开头的角色。 我不确定那会是什么。 你能用吗?

增编2

http://ideone.com/L3RNEr 的解决方案 - 基于我的最后一条评论。

using System;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
Regex rx = new Regex("^([A-Z]+[1-9][0-9]*(:[A-Z]+[1-9][0-9]*)?($|,(?!$)))*$");
Console.WriteLine(rx.IsMatch("C5:H6"));
Console.WriteLine(rx.IsMatch("C5"));
Console.WriteLine(rx.IsMatch("C5:H6,J5:P6,R5:DM6,C15"));
Console.WriteLine(rx.IsMatch("C5:H6,J5:P6,R5:DM6,C15,"));
Console.WriteLine(rx.IsMatch("C5:H6J5:P6,R5:DM6,C15"));
Console.WriteLine(rx.IsMatch(",C5:H6:J5:P6,R5:DM6,C15"));
}
}

如果你想在一个表达式中测试整个字符串的有效范围,如果你不介意在测试字符串前面加上逗号,你可以使用这个正则表达式(像这样:,C5:H6,J5:P6,R5:DM6,C15):

^(?:,[A-Z]+[1-9][0-9]*(?::[A-Z]+[1-9][0-9]*)?)*$

如果无法更改测试字符串,可以改用以下内容:

^(?:(?:^|,)[A-Z]+[1-9][0-9]*(?::[A-Z]+[1-9][0-9]*)?)*$

最新更新