我有一个正则表达式,它匹配代表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:P6
与匹配C6:H6
的相同模式匹配。
如果想要表达类似“匹配此模式1次,或*次,但仅限逗号分隔。
提前致谢!
答案 0 :(得分:1)
要删除源代码中的冗余,可以将重复的组件存储到字符串变量中,并从字符串构造正则表达式。
这样的事情:
string cellname = "[A-Z]+[1-9][0-9]*";
string cellrange = cellname + "(:" + cellname + ")?";
Regex pattern = new Regex("^" + cellrange + "(," + cellrange + ")*$")
如果你问是否有分隔符的二进制正则表达式运算符,即你可以编写的东西
A op B
并且意味着
A(BA)*
然后我害怕这样的事情不存在。 ADDENDUM :但是,你可以接近
((^|B)A)+$
这转换为“一个或多个以字符串的开头或B为前缀的As”。在这里你的B将是逗号而你的As将是范围。然后,您可以在范围内使用相同的技术,以使用冒号分隔细胞。但是(^|,)
代替(xxx|:)
,您将xxx
使用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"));
}
}
扮演单元格开头的角色。我不确定那会是什么。你可以用它吗?
ADDENDUM 2
http://ideone.com/L3RNEr处的解决方案 - 基于我上次的评论。
{{1}}
答案 1 :(得分:1)
对于任何系列的范围和单个单元格都使用正则表达式
(?!,)(?:(?:^|,)[A-Z]+(?!0)[0-9]+(?::[A-Z]+(?!0)[0-9]+)?)+
或者如果您只想匹配用逗号分隔的系列相同范围(或单个单元格),那么
^([A-Z]+(?!0)[0-9]+(?::[A-Z]+(?!0)[0-9]+)?)(,\1)*
答案 2 :(得分:1)
您可以按如下方式更改正则表达式:
^([A-Z]+[1-9][0-9]*(:[A-Z]+[1-9][0-9]*)?(,(?!$)|$))*$
关键变化是最后的这个子表达式:
(,(?!$)|$)
它匹配一个可选的逗号字符,除非它在匹配结束时,在这种情况下必须没有其他字符。这可以防止您匹配以悬挂逗号结尾的序列。
以下是相应的demo on ideone。
答案 3 :(得分:0)
如果你想在一个表达式中测试整个字符串的有效范围,你可以使用这个正则表达式,如果你不介意用逗号为测试字符串加前缀(如下所示:,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]*)?)*$