这个正则表达式应该做我期望的,即匹配“A1:B10,C3,D4:E1000”?

时间:2011-03-09 16:19:41

标签: c# .net regex vb.net

我目前正在编写一个库,我希望用户能够在四种可能的替代方案中指定电子表格单元格:

  1. 单个单元格:"A1";
  2. 多个连续的单元格:"A1:B10"
  3. 多个单独的单元格:"A1,B6,I60,AA2"
  4. 2和3的混合:"B2:B12,C13:C18,D4,E11000"
  5. 然后,为了验证输入是否遵循这些格式,我打算使用正则表达式来匹配。我在维基百科上查阅过这篇文章:
    Regular Expression (Wikipedia)

    我也发现了这个相关的问题:
    regex matching alpha character followed by 4 alphanumerics.

    根据上述链接文章中提供的信息,我会尝试使用此正则表达式:

    Default Readonly Property Cells(ByVal cellsAddresses As String) As ReadOnlyDictionary(Of String, ICell)
        Get
            Dim validAddresses As Regex = New Regex("A-Za-z0-9:,A-Za-z0-9")
    
            If (Not validAddresses.IsMatch(cellsAddresses)) then _
                Throw New FormatException("cellsAddresses")
    
            // Proceed with getting the cells from the Interop here...  
        End Get
    End Property
    
      

    问题

    1。我的正则表达是否正确?如果没有,请帮助我理解我可以使用的表达方式。

    2。 FormatExceptionInvalidExpressionException之间更有意义的例外更有意义吗?我在这里犹豫不决,因为它与属性期望输入单元格的格式有关除此之外,我正在使用(常规)表达来匹配。

    非常感谢您的帮助和支持! =)

5 个答案:

答案 0 :(得分:4)

我会尝试这个:

 [A-Za-z]+[0-9]+([:,][A-Za-z]+[0-9]+)*

说明:

  • 在[]之间是单个位置的可能字符组
  • [A-Za-z]表示从'A'到'Z'和从'a'到'z'的字符(字母)
  • [0-9]表示从0到9
  • 的字符(数字)
  • 附加到正则表达式的一部分的“+”表示:重复一次或多次
  • “*”表示:重复前一部分零次或多次。
  • ( )可用于定义组

因此,[A-Za-z]+[0-9]+匹配一个或多个字母,后跟单个单元格地址的一个或多个数字 然后,相同的块重复零次或多次,用','或':'分隔地址。

答案 1 :(得分:3)

假设电子表格的列是任意1或2个字母的值而行是任何正数,则更复杂但更严格的答案仍然是:

^[A-Z]{1,2}[1-9]\d*(:[A-Z]{1,2}[1-9]\d*)?(,[A-Z]{1,2}[1-9]\d*(:[A-Z]{1,2}[1-9]\d*)?)*$

“[A-Z] {1,2} [1-9] \ d *”是单个细胞参考的表达。如果在上面替换“[A-Z] {1,2} [1-9] \ d *”,则表达式为复数

^<cell>(:<cell>)?(,<cell>(:<cell>*)?)*$

更清楚地表明它是一个单元格或一个范围,后跟一个或多个“单元格或范围”条目,其间有逗号。

行和列指标可以进一步细化,以提供更紧密,更复杂的表达。我怀疑上面的内容可以通过前瞻或后面的断言进行简化,但我承认这些都不是我的强项。

答案 2 :(得分:3)

我认为我应该选择这个:

(([A-Z]+[1-9]\d*:)?[A-Z]+[1-9]\d*,)*([A-Z]+[1-9]\d*:)?[A-Z]+[1-9]\d*

这只允许使用大写字母作为前缀。如果您想要不区分大小写,请使用RegexOptions.IgnoreCase

您可以将[A-Z]+[1-9]\d*替换为普通旧[A-Z]\d+来简化此操作,但这只会允许使用单字母前缀,并且还允许A0和{{1}之类的内容}。由你决定。


编辑:

仔细考虑 DocMax 提及外观,并使用 Hans Kesting 的答案作为灵感,我发现这个应该工作:

B01

或者如果你想要真的扭曲的话:

^[A-Z]+\d+((,|(?<!:\w*):)[A-Z]+\d+)*$

与上一个示例一样,如果要阻止前导零,请将^([A-Z]+\d+(,|$|(?<!:\w*):))*(?<!,|:) 替换为\d+

[1-9]\d*背后的想法是,如果一个组用逗号分隔,你想让它通过;但如果它是冒号,只有在上一个分隔符不是冒号时才允许冒号。 ,|(?<!\w*:):版本很疯狂,但它允许您只使用一个(,|$|...)块来完成所有操作。

然而!虽然这个时间更短了,但我承认我觉得它有点聪明,我很遗憾这位可怜的家伙必须来从现在起六个月后继续维持。从代码 - 高尔夫的角度来看,这很有趣,但我认为最好的实际用途是使用早期版本,这样更容易阅读。

答案 3 :(得分:1)

我认为您的正则表达式不正确,请尝试(([A-Za-z0-9]*)[:,]?)*

编辑:纠正波特指出的错误:(([A-Za-z0-9]*)[:,]?)*([A-Za-z0-9]+)

最后 - 最佳版本:(([A-Za-z]+[0-9]+)[:,]?)*([A-Za-z]+[0-9]+)

//啊好吧这可能不会工作......但回答 1。 - 不,我不认为你的正则表达式是正确的

()组成一个小组

[] 形成一个charclass(你可以使用A-Z a-d 0-9等或只是单个字符)

表示1或0

* 表示0或任何

id建议阅读http://www.regular-expressions.info/reference.html

那是我前一段时间学习正则表达式的原因;)

对于构建表达式,我使用 Rad Software Regular Expression Designer

答案 4 :(得分:1)

让我们一步一步地构建它。

如果您遵循Excel寻址格式,要匹配CSL中的单个单元格条目,您将使用正则表达式:

[A-Z]{1,2}[1-9]\d*

按顺序匹配以下内容:

Any character in A to Z once or twice
Any digit in 1 to 9
Any digit zero or more times

数字表达式将阻止输入带前导零的单元格地址。

要构建允许单元格地址对的表达式,请将冒号前面的表达式重复为可选。

[A-Z]{1,2}[1-9]\d*(:[A-Z]{1,2}[1-9]\d*)?

现在允许重复前面带逗号零次或多次的模式,并添加开始和结束字符串分隔符。

^[A-Z]{1,2}[1-9]\d*(:[A-Z]{1,2}[1-9]\d*)?(,[A-Z]{1,2}[1-9]\d*(:[A-Z]{1,2}[1-9]\d*)?)*$

我承认,有点长而讨厌,但在尝试了足够多的变种之后,我找不到缩短它的方法。

希望这有用。