0

ファイル構造は次のとおりです。

"group","type","scope","name","attribute","value"
"c","","Probes Count","Counter","value","35"
"b","ProbeInformation","Probes Count","Gauge","value","0"

常に引用符を使用します。末尾の改行もあります。

これが私が持っているものです:

^(\"[^,\"]*\")(,(\"[^,\"]*\"))*(.(\"[^,\"]*\")(,(\"[^,\"]*\")))*.$

それは正しく一致していません。String.matches(regexp);を使用しています。

4

2 に答える 2

2

免責事項:コードをコンパイルしようとさえしませんでしたが、このパターンは以前は機能していました。

正規表現が何をしているのか一目でわからないときは、何が起こっているのかを理解しやすいように、それを行に分割します。不一致の親はより明白であり、コメントを追加することもできます。また、その周りにJavaコードを追加して、エスケープする奇妙な点が明らかになるようにします。

^(\"[^,\"]*\")(,(\"[^,\"]*\"))*(.(\"[^,\"]*\")(,(\"[^,\"]*\")))*.$

になります

String regex = "^" +
               "(\"[^,\"]*\")" +
               "(," +
                 "(\"[^,\"]*\")" +
               ")*" +
               "(." +
                 "(\"[^,\"]*\")" +
                 "(," +
                    "(\"[^,\"]*\")" +
                 ")" +
               ")*" +
               ".$";

ずっといい。さて、ビジネスに移りましょう。私が最初に目にするのは、引用された値に対する正規表現です。文字列内のコンマは許可されていません-おそらくあなたが望むものではありません-それでそれを修正しましょう。また、ある時点でタイプミスをしないように、それを独自の変数に入れましょう。最後に、正規表現が何をしているかを確認できるようにコメントを追加しましょう。

final String QUOTED_VALUE = "\"[^\"]*\""; // A double quote character, zero or more non-double quote characters, and another double quote
String regex = "^" +                           // The beginning of the string
               "(" + QUOTED_VALUE + ")" +      // Capture the first value
               "(," +                          // Start a group, a comma
                 "(" + QUOTED_VALUE + ")" +    // Capture the next value
               ")*" +                          // Close the group.  Allow zero or more of these
               "(." +                          // Start a group, any character
                 "(" + QUOTED_VALUE + ")" +      // Capture another value
                 "(," +                            // Started a nested group, a comma
                    "(" + QUOTED_VALUE + ")" +     // Capture the next value
                 ")" +                             // Close the nested group
               ")*" +                            // Close the group.  Allow zero or more
               ".$";                           // Any character, the end of the input

物事はさらに明確になっています。ここに2つの大きなことがわかります。

1)(私は思う)入力文字列の改行を一致させようとしています。一緒に遊んでみますが、入力を改行で分割する方が、実行している操作よりもクリーンで簡単です(これは、自分で実行できる演習です)。また、さまざまなオペレーティングシステムが持つさまざまな改行規則にも注意する必要があります(これを読んでください)。

2)キャプチャしすぎています。非キャプチャグループを使用したい場合、または出力の解析が困難でエラーが発生しやすい場合(これをお読みください)。

final String QUOTED_VALUE = "\"[^\"]*\""; // A double quote character, zero or more non-double quote characters, and another double quote
final String NEWLINE = "(\n|\n\r|\r\n)";  // A newline for (almost) any OS: Windows, *NIX or Mac
String regex = "^" +                           // The beginning of the string
               "(" + QUOTED_VALUE + ")" +   // Capture the first value
               "(?:," +                       // Start a group, a comma
                 "(" + QUOTED_VALUE + ")" + // Capture the next value
               ")*" +                       // Close the group.  Allow zero or more of these
               "(?:" + NEWLINE +            // Start a group, any character
                 "(" + QUOTED_VALUE + ")" +   // Capture another value
                 "(?:," +                       // Started a nested group, a comma
                    "(" + QUOTED_VALUE + ")" +  // Capture the next value
                 ")" +                          // Close the nested group
               ")*" +                         // Close the group.  Allow zero or more
               NEWLINE + "$";                 // A trailing newline, the end of the input

ここから、また作品を複製しているのが見えます。それを修正しましょう。これにより、元の正規表現で欠落している*も修正されます。あなたがそれを見つけることができるかどうか見てください。

final String QUOTED_VALUE = "\"[^\"]*\""; // A double quote character, zero or more non-double quote characters, and another double quote
final String NEWLINE = "(\n|\n\r|\r\n)";  // A newline for (almost) any OS: Windows, *NIX or Mac
final String LINE = "(" + QUOTED_VALUE + ")" +   // Capture the first value
                    "(?:," +                       // Start a group, a comma
                      "(" + QUOTED_VALUE + ")" + // Capture the next value
                    ")*";                        // Close the group.  Allow zero or more of these
String regex = "^" +             // The beginning of the string
               LINE +            // Read the first line, capture its values
               "(?:" + NEWLINE + // Start a group for the remaining lines
                 LINE +            // Read more lines, capture their values
               ")*" +            // Close the group.  Allow zero or more
               NEWLINE + "$";    // A trailing newline, the end of the input

少し読みやすいですよね?これで、うまくいかない場合に、大きな厄介な正規表現を分割してテストできます。

これで、正規表現をコンパイルし、マッチャーを取得して、そこからグループを取得できます。ただし、まだいくつかの問題があります。

1)先ほど、改行を壊したほうが簡単だと言いました。理由の1つは、1行にいくつの値があるかをどのように判断するかです。ハードコーディングは機能しますが、入力が変更されるとすぐに機能しなくなります。たぶんこれはあなたにとって問題ではありませんが、それでも悪い習慣です。もう1つの理由:正規表現はまだ複雑すぎて私の好みには合いません。あなたは本当にLINEに立ち寄ることで逃げることができました。

2)CSVファイルでは、次のような行が許可されます。

"some text","123",456,"some more text"

これを処理するには、引用符で囲まれた値または数字のリストのいずれかを取得する別のミニ正規表現を追加することをお勧めします。

于 2012-11-21T18:40:13.710 に答える
0

この質問:JavaでのCSV解析は、CSVを解析するためのApacheライブラリを指します。

フォーマットが実際にCSVである場合、正規表現がデータをレコードに解析することは非常に困難になります。

これはあなたの質問に直接答えるものではないことを私は知っています。CSVライブラリを使用することで、より少ない労力でより多くの成功を収めることができるでしょう。

于 2012-11-21T18:38:56.973 に答える