0

c#と正規表現を使用して固定幅のレコードを解析する必要があります。各レコードにはいくつかの固定幅フィールドが含まれており、各フィールドには重要な検証ルールが含まれている可能性があります。私が抱えている問題は、固定幅のフィールド境界を越えて適用される一致です。

ルールがないと、長さ13の固定幅の文字列を次のように4つの部分に簡単に分割できます。

(?=^.{13}$).{1}.{5}.{6}.{1}

フィールドルールの例を次に示します。フィールドはすべてスペースにするか、[AZ]で始めて、スペースを右に埋めることができます。文字の間にスペースを入れることはできません

フィールドが私が検証しなければならない唯一のものである場合、私はこれを使用することができます:

(?=^[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)

別の例:正規表現とゼロ幅の正のルックバックの間のスペース(?<=はわかりやすくするためのものです。

(?<F1>\d{2})    (?<=^.{2})
(?<F2>[A-Z]{5}) (?<=^.{7})
(?<F3>\d{4})    (?<=^.{11})
(?<F4>[A-Z]{6}) (?<=^.{17})
(?<F5>\d{4})
4

4 に答える 4

1

入力文字列のサイズが固定されている場合は、次のように、先読みと後読みを使用して特定の位置を一致させることができます。

(?<=^.{s})(?<fieldName>.*)(?=.{e}$)

どこ:

  • s=開始位置
  • e=文字列の長さ-一致する長さ-s

このように複数の正規表現を連結すると、特定の位置にあるすべてのフィールドが取得されます。

  • 固定長:10
  • フィールド1:開始0、長さ3
  • フィールド2:開始3、長さ5
  • フィールド3:開始8、長さ2

空白を無視して、この正規表現を使用します。

var match = Regex.Match("0123456789", @"
    (?<=^.{0})(?<name1>.*)(?=.{7}$)
    (?<=^.{3})(?<name2>.*)(?=.{2}$)
    (?<=^.{8})(?<name3>.*)(?=.{0}$)",
        RegexOptions.IgnorePatternWhitespace)

var field1 = match.Groups["name1"].Value;
var field2 = match.Groups["name2"].Value;
var field3 = match.Groups["name3"].Value;

フィールドに一致させたいルールを配置できます。

.*はそれらすべてに使用しましたが、そこには何でも配置できます。

例2

var match = Regex.Match(" 1a any-8888", @"
    (?<=^.{0})(?<name1>\s*\d*[a-zA-Z])(?=.{9}$)
    (?<=^.{3})(?<name2>.*)(?=.{4}$)
    (?<=^.{8})(?<name3>(?<D>\d)\k<D>*)(?=.{0}$)
    ",
        RegexOptions.IgnorePatternWhitespace)

var field1 = match.Groups["name1"].Value; // " 1a"
var field2 = match.Groups["name2"].Value; // " any-"
var field3 = match.Groups["name3"].Value; // "8888"

これがあなたの正規表現です

私はそれらすべてをテストしましたが、このサンプルはあなたが合格すべきではないと言ったものと一緒ですが、合格しました...今回は合格しません:

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
于 2012-10-20T18:16:32.867 に答える
1
Match match = Regex.Match(
  Regex.Replace(text, @"^(.)(.{5})(.{6})(.)$", "$1,$2,$3,$4"),
  @"^[A-Z ],[A-Z]*[ ]*,[A-Z]*[ ]*,[A-Z ]$");

ここでこのコードを確認してください。

于 2012-10-20T19:15:36.417 に答える
0

単一の正規表現パターンで検証できると思います

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

そのようなグループもすべてキャプチャする必要がある場合は、

^([A-Z ])([A-Z]*[ ]*)(?<=^.{6})([A-Z]*[ ]*)(?<=^.{12})([A-Z ])$
于 2012-10-20T19:20:50.577 に答える
0

私は以前にこれを投稿しましたが、この回答はあなたの質問に固有のものであり、一般化されていません。

これにより、質問で提示したすべてのケースが希望どおりに解決されます。

質問のすべてのケースをテストするプログラム

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.");
        }
    }
}
于 2012-10-20T21:02:58.947 に答える