0

私は次のような出力を持っています -

Col.A              Col.B  Col.C  Col.D
--------------------------------------------------------------
* 1  S60-01-GE-44T-AC   SGFM115001195  7520051202   A
  1  S60-PWR-AC         APFM115101302  7520047802   A
  1  S60-PWR-AC         APFM115101245  7520047802   A

また

 Col.A               Col.B  Col.C  Col.D
--------------------------------------------------------------
* 0  S50-01-GE-48T-AC   DL252040175    7590005605   B
  0  S50-PWR-AC         N/A            N/A          N/A
  0  S50-FAN            N/A            N/A          N/A

これらの出力については、正規表現 -

(?:\*)?\s+(?<unitno>\d+)\s+\S+-\d+-(?:GE|TE)?-?(?:\d+(?:F|T))-?(?:(?:AC)|V)?\s+(?<serial>\S+)\s+\S+\s+\S+\s+\n

列Aと列Bをキャプチャするのに問題なく動作しますが、最近、新しい種類の出力が得られました-

 Col.A               Col.B  Col.C  Col.D  
---------------------------------------------------------
* 0  S4810-01-64F       HADL120620060  7590009602   A        
  0  S4810-PWR-AC       H6DL120620060  7590008502   A          
  0  S4810-FAN          N/A            N/A          N/A         
  0  S4810-FAN          N/A            N/A          N/A  

ご覧のとおり、これらの出力にはパターン「GE|TE」「AC|V」がありません。下位互換性を維持しながら、それに応じて正規表現を変更するにはどうすればよいですか。

編集:

表示される出力は完全な文字列であり、操作上の制限により、ここで正規表現以外の概念を使用して目的の値を取得することはできません。ここで分割を使用するのが理想的であることは知っていますが、できません。

4

5 に答える 5

2

ここでは、正規表現は適切なアプローチではないようです。位置アプローチを使用する

string s = "* 0  S4810-01-64F       HADL120620060  7590009602   A";

bool withStar = s[0] == '*';
string nr = s.Substring(2, 2).Trim();
string colA = s.Substring(5, 18).TrimEnd();
string colB = s.Substring(24, 14).TrimEnd();
...

アップデート

正規表現に固執したい(またはしなければならない)場合は、値の代わりにスペースをテストしてください。当然、これは値にスペースが含まれていない場合にのみ機能します。

string[] result = Regex.Split(s, "\s+");

\Sもちろん、の代わりにスペース以外も検索できます\s

MatchCollection matches = Regex.Matches(s, "\S+");

または星を除く

(?:\*)?[^*\s]+
于 2012-11-28T17:29:02.430 に答える
2

読み取り不可能な巨大な正規表現を使用するよりも、 String.Split() を使用して列の値を個別の文字列に分割してから処理する方がよいでしょう。

foreach (string line in lines) {
    string[] colunnValues = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
    ...
}
于 2012-11-28T17:29:20.013 に答える
1

これらのレポートの解析に正規表現は使用しません。

代わりに、ヘッダーが削除された後、固定列幅のレポートとして扱います。

私は次のようにします(これは例としてコールドで入力されており、構文についてもテストされていません):

   // Leaving off all public/private/error detection stuff
   class ColumnDef  
   {
        string Name { set; get; } 
        int FirstCol { set; get; }
        int LastCol { set; get; }
   }

   ColumnDef[] report = new ColumnDef[] 
   {
         { Name = "ColA",
           FirstCol = 0,
           LastCol = 2
         },
         /// ... and so on for each column
   }

   IDictionary<string, string> ParseDataLine(string line) 
   {
       var dummy = new Dictionary<string, string>();
       foreach (var c in report) 
       {
          dummy[c.Name] = line.Substring(c.FirstCol, c.LastCol).Trim();
       }
   }

これは、一般的な ETL (Extract、Transform、および Load) の問題、特に Extract ステージの例です。

を使用する前にヘッダーとフッターの行を削除するParseDataLine必要がありますが、それを行うのに十分な情報が表示されているかどうかはわかりません. あなたの投稿の内容に基づいて、空白の行、またはスペースまたは a で始まらない*行は無視されるヘッダー/フッター行です。

于 2012-11-28T17:33:07.323 に答える
1

このようなことを試してみませんか(?:\*)?\s+(?<unitno>\d+)\s+\S+\s+(?<serial>\S+)\s+\S+\s+\S+(?:\s+)?\n

これは提供された正規表現から構築され、提供された\n入力は末尾にあるため、キャリッジ リターンで終了する必要があります。

于 2012-11-28T17:55:56.917 に答える
1

GEあなたの正規表現はorさえ必要としませんTE?後にそれを参照してください(?:GE|TE)

つまり、前のグループまたはシンボルはオプションです。

ACandVセクションについても同様です。

于 2012-11-28T17:25:18.390 に答える