6

二重引用符で囲まれたすべての文字列を一致させたいテキストがあるとします。ただし、これらの二重引用符内に二重引用符を含めることができます。例:

"He said \"Hello\" to me for the first time"

正規表現を使用して、これを効率的に一致させるにはどうすればよいですか?

4

1 に答える 1

17

このような入力を一致させるための非常に効率的なソリューションは、normal* (special normal*)*パターンを使用することです。この名前は、Jeffrey Friedl の優れた書籍Mastering Regular Expressionsから引用されています。

これは、通常のエントリ (通常の部分) とその間の区切り文字 (特別な部分) で構成される入力を一致させるのに一般的に役立つパターンです。

すべての正規表現と同様に、より良い選択肢がない場合に使用する必要があることに注意してください。このパターンを使用して CSV データを解析することもできますが、たとえば Java を使用している場合は、代わりに OpenCSV を使用することをお勧めします。

また、パターン名の量指定子は星 (つまり、0 個以上) ですが、必要に応じて変更できることにも注意してください。

二重引用符が埋め込まれた文字列

上記の例をもう一度見てみましょう。このテキスト サンプルは、入力のどこにでもある可能性があることを考慮してください。

"He said \"Hello\" to me for the first time"

どんなに頑張っても、「ドットと貪欲/怠惰な量指定子」の魔法をいくら使っても、問題を解決することはできません。代わりに、引用符の間の入力を通常と特別に分類します。

  • 通常は、バックスラッシュまたは二重引用符以外のものです[^\\"]
  • special は、バックスラッシュとそれに続く二重引用符のシーケンスです: \\".

これをパターンに代入するとnormal* (special normal*)*、次の正規表現が得られます。

[^\\"]*(\\"[^\\"]*)*

全文を一致させるために二重引用符を追加すると、最終的な正規表現が得られます。

"[^\\"]*(\\"[^\\"]*)*"

これは空の引用符付き文字列にも一致することに注意してください。

ダッシュ区切りのある単語

ここでは、次の理由から、量指定子にバリアントを使用する必要があります。

  • 私たちは空の言葉を望んでいません。
  • ダッシュで始まる単語は必要ありません。
  • ダッシュが表示される場合、別のダッシュがある場合はその前に少なくとも 1 つの文字が必要です。

簡単にするために、小文字の ASCII 文字のみが許可されていると仮定します。

サンプル入力:

the-word-to-match

再びノーマルとスペシャルに分解してみましょう。

  • 通常: 小文字、ASCII 文字: [a-z];
  • 特別: ダッシュ:-

パターンの正規形は次のようになります。

[a-z]*(-[a-z]*)*

しかし、私たちが言ったように:

  • ダッシュで始まる単語は必要ありません。最初の単語は;*になる必要があります。+
  • ダッシュが見つかった場合、その後に少なくとも 1 つの文字が必要です。2 番目の文字*は になり+ます。

最終的には次のようになります。

[a-z]+(-[a-z]+)*

その周りに単語アンカーを追加して、最終結果を取得します。

\b[a-z]+(-[a-z]+)*\b

その他のオペレーターのバリエーション

上記の例は、 で置き換えることに限定されて*+ますが、もちろん、必要な数のバリエーションを持つことができます。超古典的な例の 1 つは、IP アドレスです。

  • 通常は3桁まで(\d{1,3})、
  • 特別なのはドット: ( \.),
  • 最初のものは 1normal回しか現れないため、量指定子はありません。
  • normal内側(special normal*)も 1 回しか現れないため、量指定子はありません。
  • 最終的にその(special normal*)部分はちょうど 3 回表示されます{3}

これにより、式が得られます(単語アンカーで装飾されています):

\b\d{1,3}(\.\d{1,3}){3}\b

結論

このパターンの柔軟性により、正規表現ツールボックスの中で最も便利なツールの 1 つになります。ライブラリが存在する場合に正規表現を使用してはならない多くの問題が存在しますが、場合によっては正規表現を使用する必要があります。少し練習すれば、これはあなたの親友の 1 つになるでしょう。

チップ

  • 繰り返し部分 (部分) をキャプチャする必要がない (またはキャプチャしたくない) 可能性が高いです(special normal*)。したがって、非キャプチャ グループを使用することをお勧めします。たとえば、"[^\\"]*(?:\\"[^\\"]*)*"引用符で囲まれた文字列に使用します。実際、あなたがそれを望んでいたとしても、この場合、キャプチャーが望ましい結果につながることはほとんどありません。なぜなら、このパターンを。ネット。(@ohaal に感謝)
于 2013-06-11T12:01:34.997 に答える