1

第一次发帖,老用户。我不明白为什么这个正则表达式的数据在它应该失败时会通过。快速概述是我有一个带有管道分隔数据的文本文件。我一次阅读每一行,并与正则表达式进行比较以判断通过/失败。

这是有问题的数据:

|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|#|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

4 回答 4

4

这是一个匹配,因为.{0,25}不仅匹配,RGT Foods, Inc.而且匹配091091|它之前的。

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

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

  • [\|]可以写成[|]\|
  • {1}可以完全移除;默认为“匹配一次”。
  • [A-Z,a-z,0-9]匹配 AZ、az、0-9和逗号。你可能的意思是[A-Za-z0-9]。同样[0,1]应该是[01][0-9,A-Z]应该是[0-9A-Z]

不过,老实说,如果您知道您的自由字段不能包含管道,我会String.Split在管道上单独验证每个字段。那个正则表达式是一场噩梦。

于 2012-12-17T14:58:09.730 回答
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}\|
于 2012-12-17T14:58:20.200 回答
0

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

于 2012-12-17T14:57:23.680 回答
0

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

一个流行的选项是FileHelpers,它Microsoft.VisualBasic.FileIO具有为此而设计的TextFieldParser类。

于 2012-12-17T15:00:09.777 回答