C# 如何使用正则表达式将具有复杂规则的固定宽度字符串解析为组件字段

C# 如何使用正则表达式将具有复杂规则的固定宽度字符串解析为组件字段,c#,regex,C#,Regex,我需要使用c#和正则表达式解析固定宽度的记录。 每个记录都包含许多固定宽度的字段,每个字段都可能具有非平凡的验证规则。我遇到的问题是在固定宽度的字段边界上应用匹配 如果没有规则,很容易将长度为13的固定宽度字符串分成如下4部分: (?=^.{13}$).{1}.{5}.{6}.{1} (?<=^.{s})(?<fieldName>.*)(?=.{e}$) 下面是一个示例字段规则: 字段可以是所有空格,也可以以[A-Z]开头,并用空格右填充。字母之间不能有空格 如果字段是我唯

我需要使用c#和正则表达式解析固定宽度的记录。 每个记录都包含许多固定宽度的字段,每个字段都可能具有非平凡的验证规则。我遇到的问题是在固定宽度的字段边界上应用匹配

如果没有规则,很容易将长度为13的固定宽度字符串分成如下4部分:

(?=^.{13}$).{1}.{5}.{6}.{1}
(?<=^.{s})(?<fieldName>.*)(?=.{e}$)
下面是一个示例字段规则: 字段可以是所有空格,也可以以[A-Z]开头,并用空格右填充。字母之间不能有空格

如果字段是我唯一需要验证的内容,我可以使用:

(?=^[A-Z ]{5}$)([ ]{5}|[A-Z]+[ ]*)
当我将此验证作为较长列表的一部分添加时,我必须从前瞻中删除“^”和“$”,然后我开始获得长度不为5的匹配项

下面是完整的正则表达式以及一些应匹配和不匹配表达式的示例文本

(?=^[A-Z ]{13}$)A(?=[A-Z ]{5})([ ]{5}|(?>[A-Z]{1,5})[ ]{0,4})(?=[A-Z ]{6})([ ]{6}|(?>[A-Z]{1,6})[ ]{0,5})Z
我如何实现规则,以便每个字段的下一个XX字符用于匹配,并确保匹配不会重叠

应匹配的行:

ABCDEFGHIJKLZ
A           Z
AB          Z
A     G     Z
AB    G     Z
ABCDEF      Z
ABCDEFG     Z
A     GHIJKLZ
AB    GHIJKLZ
不应匹配的行:

AB D        Z
AB D F      Z
AB   F      Z
A     G I   Z
A     G I  LZ
A     G    LZ
AB   FG    LZ
AB D FG     Z
AB   FG I   Z
AB D FG i   Z
以下3项不应匹配,但应匹配

AB   FG     Z
AB   FGH    Z
AB  EFGH    Z

编辑: 通用解决方案(基于Ωmega的答案)为清晰起见,带有命名捕获:

(?<F1>F1Regex)(?<=^.{Len(F1)})
(?<F2>F2Regex)(?<=^.{Len(F1+F2)})
(?<F3>F3Regex)(?<=^.{Len(F1+F2+F3)})
               ...
(?<Fn>FnRegex)

(?F1Regex)(?如果输入字符串大小固定,则可以使用look aheads和look behinds匹配特定位置,如下所示:

(?=^.{13}$).{1}.{5}.{6}.{1}
(?<=^.{s})(?<fieldName>.*)(?=.{e}$)
这是您的正则表达式

我测试了所有样本,但这个样本与您说的不应该通过,但通过的样本相同……这次,它不会通过:

var match = Regex.Match("AB   FG     Z", @"
    ^A
    (?<=^.{1})  (?<name1>([ ]{5}|(?>[A-Z]{1,5})[ ]{0,4}))  (?=.{7}$)
    (?<=^.{6})  (?<name2>([ ]{6}|(?>[A-Z]{1,6})[ ]{0,5}))  (?=.{1}$)
    Z$
    ",
        RegexOptions.IgnorePatternWhitespace)

// no match with this input string
var match=Regex.match(“AB FG Z,@”
^A
(?[A-Z]{1,5}][{0,4}))(?=.{7}$)
(?[A-Z]{1,6}][{0,5}])(?=.{1}$)
Z$
",
RegexOptions.ignorepattern(空格)
//与此输入字符串不匹配

检查此代码

我认为可以通过单个正则表达式模式对其进行验证

^[A-Z ][A-Z]*[ ]*(?<=^.{6})[A-Z]*[ ]*(?<=^.{12})[A-Z ]$

^[A-Z][A-Z]*[]*(?我之前已经发布过这个,但是这个答案更具体地针对您的问题,而不是一般性的

这解决了您在问题中提出的所有案例,符合您的要求

测试问题中所有案例的程序

class Program
{
    static void Main()
    {
        var strMatch = new string[]
                      {
                          // Lines that should match:
                          "ABCDEFGHIJKLZ",
                          "A           Z",
                          "AB          Z",
                          "A     G     Z",
                          "AB    G     Z",
                          "ABCDEF      Z",
                          "ABCDEFG     Z",
                          "A     GHIJKLZ",
                          "AB    GHIJKLZ",
                      };


        var strNotMatch = new string[]
                      {
                          // Lines that should not match:
                          "AB D        Z",
                          "AB D F      Z",
                          "AB   F      Z",
                          "A     G I   Z",
                          "A     G I  LZ",
                          "A     G    LZ",
                          "AB   FG    LZ",
                          "AB D FG     Z",
                          "AB   FG I   Z",
                          "AB D FG i   Z",

                          // The following 3 should not match but do.
                          "AB   FG     Z",
                          "AB   FGH    Z",
                          "AB  EFGH    Z",
                      };

        var pattern = @"
                ^A
                (?<=^.{1})  (?<name1>([ ]{5}|(?>[A-Z]{1,5})[ ]{0,4}))  (?=.{7}$)
                (?<=^.{6})  (?<name2>([ ]{6}|(?>[A-Z]{1,6})[ ]{0,5}))  (?=.{1}$)
                Z$
                ";

        foreach (var eachStrThatMustMatch in strMatch)
        {
            var match = Regex.Match(eachStrThatMustMatch,
                pattern, RegexOptions.IgnorePatternWhitespace);

            if (!match.Success)
                throw new Exception("Should match.");
        }


        foreach (var eachStrThatMustNotMatch in strNotMatch)
        {
            var match = Regex.Match(eachStrThatMustNotMatch,
                pattern, RegexOptions.IgnorePatternWhitespace);

            if (match.Success)
                throw new Exception("Should match.");
        }
    }
}
类程序
{
静态void Main()
{
var stratch=新字符串[]
{
//应匹配的行:
“ABCDEFGHIJKLZ”,
“A Z”,
“AB Z”,
“A G Z”,
“AB G Z”,
“ABCDEF Z”,
“ABCDEFG Z”,
“GHIJKLZ”,
“AB GHIJKLZ”,
};
var strNotMatch=新字符串[]
{
//不应匹配的行:
“AB D Z”,
“AB D F Z”,
“AB F Z”,
“A G I Z”,
“A G I LZ”,
“A G LZ”,
“AB FG LZ”,
“AB D FG Z”,
“AB FG I Z”,
“AB D FG i Z”,
//以下3项不应匹配,但应匹配。
“AB FG Z”,
“AB FGH Z”,
“AB EFGH Z”,
};
变量模式=@“
^A
(?[A-Z]{1,5}][{0,4}))(?=.{7}$)
(?[A-Z]{1,6}][{0,5}])(?=.{1}$)
Z$
";
foreach(在格式中必须匹配的变量eachstr)
{
var match=Regex.match(每个必须匹配的,
模式,RegexOptions.IgnorePatternWhitespace);
如果(!match.Success)
抛出新异常(“应匹配”);
}
foreach(在strNotMatch中必须不匹配的变量eachstr)
{
var match=Regex.match(每个必须不匹配的,
模式,RegexOptions.IgnorePatternWhitespace);
如果(匹配成功)
抛出新异常(“应匹配”);
}
}
}

在使用.Net正则表达式类时,我建议您使用我发布的这个工具,根据您的具体情况,使用一个正则表达式解决问题。如果您发现更多困难,请告诉我们。=)@Ωmega有一个比我简单得多的正则表达式。。。我认为这是正确的答案。@JayWalker:如果需要提取字段的值:
^[A-Z]([A-Z]*[]*)(?@MiguelAngelo-问题要求验证,即使OP的代码也没有显示任何捕获的迹象,因此我相信我的答案正是他所要求的…我明白了,但是OP正则表达式确实有捕获…也许他不仅仅是在验证。@MiguelAngelo-我已经用捕获组更新了所有4个部分的答案,以防OP需要。。Miguel,你的解决方案非常好,因为它可以应用于任意数量的字段(我的实际问题有11个)。
^[A-Z ][A-Z]*[ ]*(?<=^.{6})[A-Z]*[ ]*(?<=^.{12})[A-Z ]$
^([A-Z ])([A-Z]*[ ]*)(?<=^.{6})([A-Z]*[ ]*)(?<=^.{12})([A-Z ])$
class Program
{
    static void Main()
    {
        var strMatch = new string[]
                      {
                          // Lines that should match:
                          "ABCDEFGHIJKLZ",
                          "A           Z",
                          "AB          Z",
                          "A     G     Z",
                          "AB    G     Z",
                          "ABCDEF      Z",
                          "ABCDEFG     Z",
                          "A     GHIJKLZ",
                          "AB    GHIJKLZ",
                      };


        var strNotMatch = new string[]
                      {
                          // Lines that should not match:
                          "AB D        Z",
                          "AB D F      Z",
                          "AB   F      Z",
                          "A     G I   Z",
                          "A     G I  LZ",
                          "A     G    LZ",
                          "AB   FG    LZ",
                          "AB D FG     Z",
                          "AB   FG I   Z",
                          "AB D FG i   Z",

                          // The following 3 should not match but do.
                          "AB   FG     Z",
                          "AB   FGH    Z",
                          "AB  EFGH    Z",
                      };

        var pattern = @"
                ^A
                (?<=^.{1})  (?<name1>([ ]{5}|(?>[A-Z]{1,5})[ ]{0,4}))  (?=.{7}$)
                (?<=^.{6})  (?<name2>([ ]{6}|(?>[A-Z]{1,6})[ ]{0,5}))  (?=.{1}$)
                Z$
                ";

        foreach (var eachStrThatMustMatch in strMatch)
        {
            var match = Regex.Match(eachStrThatMustMatch,
                pattern, RegexOptions.IgnorePatternWhitespace);

            if (!match.Success)
                throw new Exception("Should match.");
        }


        foreach (var eachStrThatMustNotMatch in strNotMatch)
        {
            var match = Regex.Match(eachStrThatMustNotMatch,
                pattern, RegexOptions.IgnorePatternWhitespace);

            if (match.Success)
                throw new Exception("Should match.");
        }
    }
}