为什么这个正则表达式与额外字段匹配?

时间:2012-12-17 14:50:45

标签: c# regex expression match

第一次海报,长时间用户。我无法弄清楚为什么这个正则表达式的数据在失败时会传递。快速概述我有一个文本文件,其中包含管道分隔数据。我一次只读一行,并与正则表达式进行通过/失败比较。

以下是有问题的数据:

|A|00032004|00032004|25 S Kings Highway||Cape Giradeau|MO|63701|345800886888|0000254575|091091|RGT Foods, Inc.|1|345800886888|1|345800886888|1|601103061404806|1|003241699917|0|000000000000|0|000000000000|0|000000000000|0|000000000000|
|A|00032005|00032005|1009 Kings Hwy||Rolla |MO|65401|345800885880|0000254564||RGT Foods, Inc.|1|345800885880|1|345800885880|1|601103061404798|1|003241699925|0|000000000000|0|000000000000|0|000000000000|0|000000000000|

以下是基本细分: | D,U或A | ID#| ID#| St Add1 | St Add2 | City | ST | Zip |#|#| Name | bool |#| bool |#| bool |#| bool |#| bool | #|布尔|#|布尔|#|布尔|#|

这是我的正则表达式(警告:它有点长):

^[\|]{1}[DUA]{1}[\|]{1}[0-9,A-Z]{8}[\|]{1}[0-9,A-Z]{8}[\|]{1}.{0,25}[\|]{1}.{0,25}[\|]{1}.{0,25}[\|]{1}[A-Z,a-z]{2}[\|]{1}[0-9]{5}[\|]{1}[A-Z,a-z,0-9]{12}[\|]{1}[A-Z,a-z,0-9]{10}[\|]{1}.{0,25}[\|]{1}[0,1]{1}[\|]{1}[0-9]{12}[\|]{1}[0,1]{1}[\|]{1}[0-9]{12}[\|]{1}[0,1]{1}[\|]{1}[0-9]{15}[\|]{1}[0,1]{1}[\|]{1}[0-9]{12}[\|]{1}[0,1]{1}[\|]{1}[0-9]{12}[\|]{1}[0,1]{1}[\|]{1}[0-9]{12}[\|]{1}[0,1]{1}[\|]{1}[0-9]{12}[\|]{1}[0,1]{1}[\|]{1}[0-9]{12}[\|]{1}

这是我的正则函数:

//Compare the entire line at once
public static bool MatchCCRegEx(string spLine)
{
    try
    {
        Regex CCLineCheck = new Regex(
                Properties.Settings.Default.CCRegExValidationString);
        Match CCLineMatch = CCLineCheck.Match(spLine);

        if (CCLineMatch.Success)
            return true;
        else
            return false;
    }
    catch (Exception RegExCheckExc)
    {
        WELogger.LogEvent("3", 
            "Error running RegEx check on this line:\r\n" 
            + spLine + "\r\n" + RegExCheckExc.ToString());

        Environment.Exit(9);
        return false;
    }
}

我给出的示例数据应该失败,因为#和Name之间有一个额外的字段,值为091091.第二行也应该因为额外的字段而失败(但在那个字段上它是空的)。我已经盯着正则表达几个小时了,因为在“#|#| Name | bool”看起来像我这样,091091会被用于名称和传递,但是“RGT Foods,Inc。”不应该传递为0或1 ...但两条线都通过正则表达式,我做错了什么?

感谢。

4 个答案:

答案 0 :(得分:4)

这是匹配,因为.{0,25}不仅与RGT Foods, Inc.匹配,还与之前的091091|匹配。

如果您知道“免费”字段不包含任何管道,请将.{0,25}替换为[^|]{0,25}。 (“零至25个非管道字符”。)

另外,为了便于阅读,请注意

  • [\|]可以写为[|]\|
  • {1}可以完全删除;默认为“匹配一次”。
  • [A-Z,a-z,0-9]匹配A-Z,a-z,0-9 和逗号。你可能意味着[A-Za-z0-9]。同样,[0,1]应为[01][0-9,A-Z]应为[0-9A-Z]

老实说,如果你知道你的免费字段不能包含管道,我只需在管道上String.Split并分别验证每个字段。那个正则表达式是一场噩梦。

答案 1 :(得分:1)

问题在于,您允许|作为分隔符之间匹配的一部分。你可能不想这样做。此外,您可以减少大量的多余括号,因为{1}是不必要的。您可能不想允许使用逗号:

^\|[DUA]\|[0-9A-Z]{8}\|[0-9A-Z]{8}\|[^|]{0,25}\|[^|]{0,25}\|[^|]{0,25}\|[A-Za-z]{2}\|[0-9]{5}\|[A-Za-z0-9]{12}\|[A-Za-z0-9]{10}\|[^|]{0,25}\|[01]\|[0-9]{12}\|[01]\|[0-9]{12}\|[01]\|[0-9]{15}\|[01]\|[0-9]{12}\|[01]\|[0-9]{12}\|[01]\|[0-9]{12}\|[01]\|[0-9]{12}\|[01]\|[0-9]{12}\|

答案 2 :(得分:0)

.{0,25}匹配任何内容(长度为0-25),包括 |。尝试[^\|]{0,25}排除| s。

答案 3 :(得分:0)

我建议使用为此任务构建的库,而不是使用正则表达式来解析分隔文件。

一个受欢迎的选项是FileHelpersMicrosoft.VisualBasic.FileIO具有为此制作的TextFieldParser类。