166

正規表現がよくわかりません。それらを分かりやすく教えていただけませんか?オンラインのツールや書籍があれば、それらへのリンクもお願いできますか?

4

1 に答える 1

824

最も重要な部分はコンセプトです。構成要素がどのように機能するかを理解すると、構文の違いは軽度の方言にすぎません。正規表現エンジンの構文の上にあるレイヤーは、使用しているプログラミング言語の構文です。Perl などの言語では、この複雑さのほとんどが取り除かれますが、C プログラムで正規表現を使用している場合は、他の考慮事項に留意する必要があります。

正規表現を好きなように組み合わせて使用​​できる構成要素と考えると、独自のパターンを作成してデバッグする方法だけでなく、他の人が作成したパターンを理解する方法を学ぶのにも役立ちます。

シンプルに始める

概念的には、最も単純な正規表現はリテラル文字です。パターンNは文字「N」に一致します。

互いに隣接する正規表現はシーケンスに一致します。たとえば、このパターンNickは、'N' の後に 'i' が続き、'c' と 'k' が続くシーケンスに一致します。

Unix で正規表現を使用したことがある場合はgrep、通常の見た目の文字列を検索するためだけであっても、既に正規表現を使用しています。( reingrepは正規表現を指します。)

メニューから注文

少し複雑にすると、'Nick' または 'nick' のいずれかを pattern に一致させることができます[Nn]ick。角括弧で囲まれた部分は文字クラスです。つまり、囲まれた文字の 1 つに正確に一致します。文字クラスで範囲を使用することもできるため、[a-c]「a」または「b」または「c」のいずれかに一致します。

このパターン.は特殊です。ドットのみに一致するのではなく、任意の文字†</sup> に一致します。概念的には本当に大きな文字クラスと同じ[-.?+%$A-Za-z0-9...]です。

文字クラスをメニューと考えてください。1 つだけ選択してください。

便利なショートカット

を使用.すると、多くの入力を節約できます。また、一般的なパターンのショートカットは他にもあります。数字を一致させたいとします。これを書く 1 つの方法は です[0-9]。数字は頻繁に一致するターゲットであるため、代わりにショートカットを使用でき\dます。その他は\s(空白) と\w(単語文字: 英数字またはアンダースコア) です。

大文字のバリアントはそれらの補数であるため、たとえば、\S空白文字に一致します。

一度じゃ足りない

そこから、量指定子を使用してパターンの一部を繰り返すことができます。たとえば、パターンはab?c'abc' または 'ac' に一致?します。これは、修飾子が変更するサブパターンをオプションにするためです。他の数量詞は

  • *(ゼロ回以上)
  • +(1回以上)
  • {n}(正確にn回)
  • {n,}(少なくともn回)
  • {n,m}( n回以上m回以下)

これらのブロックのいくつかを組み合わせると、パターン[Nn]*ickはすべてのブロックに一致します。

  • 病気
  • ニック
  • ニック
  • ニック
  • ニック
  • ニック
  • (等々)

最初の一致は重要な教訓を示しています:*常に成功する! どのパターンも 0 回一致する可能性があります。

他のいくつかの有用な例:

  • [0-9]+(およびそれに相当する\d+) は、任意の非負の整数に一致します
  • \d{4}-\d{2}-\d{2}2019-01-01 のような形式の日付に一致します

グループ化

数量詞は、パターンをすぐ左に変更します。0abc+0'0abc0'、'0abcabc0' などと一致すると思われるかもしれませんが、プラス数量詞のすぐc左側のパターンは です。これは0abc+0、「0abc0」、「0abcc0」、「0abccc0」などに一致することを意味します。

末尾がゼロの 'abc' の 1 つ以上のシーケンスに一致させるには、 を使用します0(abc)+0。括弧は、単位として定量化できるサブパターンを示します。正規表現エンジンが、括弧で囲まれたグループに一致する入力テキストの部分を保存または「キャプチャ」することも一般的です。この方法でビットを抽出すると、インデックス と をカウントするよりもはるかに柔軟で、エラーが発生しにくくなりますsubstr

オルタネーション

前に、'Nick' または 'nick' のいずれかに一致する 1 つの方法を見ました。もう 1 つは のように交替Nick|nickです。交代には、左側のすべてと右側のすべてが含まれることを忘れないでください。の範囲を制限するには、グループ化括弧を使用します|(例: ) (Nick|nick)

[a-c]別の例として、 と同様に書くこともできますがa|b|c、多くの実装では、代替の長さが 1 より大きいと想定されているため、これは最適ではない可能性があります。

逃げる

一部の文字はそれ自体に一致しますが、その他の文字には特別な意味があります。このパターンは、バックスラッシュの\d+後に小文字の D が続き、その後にプラス記号が続くものと一致しません。それを取得するには、 を使用します\\d\+。バックスラッシュは、後続の文字から特別な意味を取り除きます。

貪欲

正規表現量指定子は貪欲です。これは、パターン全体が正常に一致できるようにしながら、可能な限り多くのテキストに一致することを意味します。

たとえば、入力が

「こんにちは」と彼女は言った、「お元気ですか?」

'Hello' だけに一致することを期待するかもしれませんが".+"、'Hello' から 'you?' までずっと一致していることに驚くでしょう。

貪欲から用心深いと思われるものに切り替える?には、数量詞に余分なものを追加します。\((.+?)\)これで、質問の例がどのように機能するかがわかりました。これは、リテラルの左括弧のシーケンスに一致し、その後に 1 つ以上の文字が続き、右括弧で終了します。

入力が「(123) (456)」の場合、最初のキャプチャは「123」になります。貪欲でない量指定子は、パターンの残りの部分ができるだけ早く一致を開始できるようにしたいと考えています。

(あなたの混乱に関して言えば、どこで((.+?))同じことをする正規表現方言を私は知りません。途中のどこかで何かが伝達で失われたのではないかと思います。)

アンカー

特殊なパターン^を使用して、入力の最初だけで$一致し、最後だけで一致させます。自分のパターンで「表と裏はわかっているけど、その間は全部ください」という「ブックエンド」を作るのは便利なテクニックです。

フォームのコメントを一致させたいとします

-- This is a comment --

あなたは書くでしょう^--\s+(.+)\s+--$

あなた自身のものをつくる

正規表現は再帰的であるため、これらの基本的なルールを理解したので、好きなように組み合わせることができます。

正規表現を作成およびデバッグするためのツール:

書籍

無料のリソース

脚注

†:任意の文字に一致する上記のステートメント.は、厳密には正しくない教育目的のための単純化です。ドットは、改行を除くすべての文字に一致します"\n"が、実際には.+、改行の境界を越えるようなパターンを想定することはほとんどありません。Perl 正規表現には、たとえば、任意の文字に一致させるための/sスイッチと Javaがあります。そのような機能を持たない言語の場合、「任意の空白または任意の非空白」、つまり何でも一致するようなものを使用できます。Pattern.DOTALL.[\s\S]

于 2010-05-03T16:09:21.150 に答える