3

apple404, orange pie, wind\,cool, sun\\mooon, earth,JavaのようなCSV文字列があります。正確には、csv 文字列の各値は、コンマとバックスラッシュがバックスラッシュを使用してエスケープされている場合、任意のものにすることができます。

最初の 5 つの値を見つけるには、正規表現が必要です。いくつかのゴーグルの後、私は次のことを思いつきました。ただし、値内でエスケープされたコンマは許可されません。

Pattern pattern = Pattern.compile("([^,]+,){0,5}");
Matcher matcher = pattern.matcher("apple404, orange pie, wind\\,cool, sun\\\\mooon, earth,");
    if (matcher.find()) {
        System.out.println(matcher.group());
    } else {
        System.out.println("No match found.");
    }

値内のエスケープされたコンマに対して機能させる方法を知っている人はいますか?

4

3 に答える 3

2

次の否定的な後読みベースの正規表現は機能します。

 Pattern pattern = Pattern.compile("(?:.*?(?<!(?:(?<!\\\\)\\\\)),){0,5}");

ただし、本格的な CSV 解析を行うには、JavaCSVなどの専用の CSV パーサーを使用することをお勧めします。

于 2013-08-24T05:28:38.093 に答える
1

この正規表現はうまく機能します。バックスラッシュでエスケープされたコンマだけでなく、バ​​ックスラッシュでエスケープされたバックスラッシュも正しく認識します。また、生成される一致にはカンマが含まれていません。

/(?:\\\\|\\,|[^,])*/g

(Java 文字列リテラル内でこの正規表現を表す場合、区切り文字を引用符に置き換え、すべてのバックスラッシュを 2 倍にすることを理解して、標準の正規表現表記を使用しています。)

入力例

"apple404, オレンジパイ, 風\,涼しさ, 太陽\\,月, 地球"

この出力を生成します

  1. 「りんご404」

  2. 「オレンジパイ」

  3. 「風\、涼しい」

  4. " 太陽\\"

  5. 「ムーン」

「sun」の後の二重バックスラッシュはエスケープされるため、次のコンマはエスケープされないことに注意してください。

この正規表現が機能する方法は、最初に入力を最長のシーケンスに原子化することです。最初に 2 つのバックスラッシュ (可能なマルチバイト文字値の代替の 1 つとして扱います) で始まり、エスケープされたコンマ (2 つ目の可能なマルチバイト文字の代替として扱われます) が続きます。カンマ以外の値で。これらのアトムの任意の数が一致し、その後にリテラル コンマが続きます。

最初の N 個のフィールドを取得するには、前の回答からの一致の配列をスプライスするか、主な式を追加の括弧で囲み、オプションのコンマを含めてフィールド間の内容を一致させ、それをフィールドの先頭に固定します。エンジンがそれ以上 N 個のフィールドのグループを返さないように文字列を変更し、それを数値化します (ここでは N = 5 を使用):

/^((?:\\\\|\\,|[^,])*,?){0,5}/g

繰り返しますが、標準の正規表現表記法を使用していますが、ここでは、これを Java 文字列として引用する簡単な演習も行います。

"^((?:\\\\\\\\|\\\\,|[^,])*,?){0,5}"

これは、OPで指定された正確な要件の両方の部分に実際に答える、このページの唯一のソリューションです。「...カンマとバックスラッシュは、バックスラッシュを使用してエスケープされます。」入力についてはfi\,eld1\\,field2\\,field3\\,field4\\,field5\\,field6\\,、最初の 5 つのフィールドのみが適切に一致しますfi\,eld1\\,field2\\,field3\\,field4\\,field5\\,

:私の最初の回答は、OPの元のコードとサンプルデータの暗黙の一部である同じ仮定を作成しました。これには、すべてのフィールドに続くコンマが必要でした。問題は、入力が正確に 5 フィールド以下であり、最後のフィールドの後にコンマが続いていない場合 (同等に空のフィールドが続く場合)、最終フィールドが一致しないことでした。私はこれが気に入らなかったので、両方の回答を更新して、次のコンマを必要としないようにしました。

この回答の欠点は、コンマ間の値に「何か」とエスケープされたコンマまたはエスケープされたバックスラッシュが含まれるというOPの仮定に従うことです(つまり、二重引用符などの文字列は区別されず、エスケープされたコンマとバックスラッシュのみが認識されます)。私の答えは、その架空のシナリオの基準を満たしています。しかし実際には、円記号を使用せずにフィールド内にカンマを含めるために、CSV フィールドを二重引用符で囲むことができると考える人もいるでしょう。

したがって、@anubhava の言葉を繰り返し、CSV データを処理するときは常に「本物の」CSV パーサーを使用することを提案します。それ以外のことを行うのは、スクリプトのキディであり、CSV データを真に「処理」することではありません。

Javaの評価結果

于 2013-08-24T05:30:17.223 に答える