正規表現の学習[終了]


166

正規表現がよくわかりません。わかりやすく説明してもらえますか?オンラインツールや本がある場合は、それらにもリンクしていただけませんか。

回答:


789

最も重要な部分は概念です。ビルディングブロックがどのように機能するかを理解すると、構文の違いは穏やかな方言に過ぎません。正規表現エンジンの構文の上のレイヤーは、使用しているプログラミング言語の構文です。Perlなどの言語はこの複雑さのほとんどを取り除きますが、Cプログラムで正規表現を使用している場合は、他の考慮事項に留意する必要があります。

正規表現を自由に組み合わせて照合できる構成要素と考える場合は、独自のパターンを記述してデバッグする方法だけでなく、他の人が記述したパターンを理解する方法も学ぶことができます。

シンプルに始める

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

隣同士の正規表現はシーケンスを照合します。たとえば、パターンNickは、「N」、「i」、「c」、「k」の順に一致します。

grepUnixでこれまで使用したことがあれば、たとえ普通に見える文字列を検索するだけでも、すでに正規表現を使用していることになります。(rein grepは正規表現を指します。)

メニューから注文する

少しだけ複雑さを追加して、「ニック」または「ニック」をパターンに一致させることができます[Nn]ick。角括弧で囲まれた部分は文字クラスです。つまり、囲まれた文字の1つと完全に一致します。文字クラスで範囲を使用することもできるため[a-c]、「a」、「b」、または「c」のいずれかに一致します。

パターン.は特殊です。リテラルのドットだけではなく、任意の文字に一致します。概念的には、非常に大きな文字クラスと同じ[-.?+%$A-Za-z0-9...]です。

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

役立つショートカット

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

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

一度では足りない

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

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

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

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

最初の試合は重要な教訓を示しています。*常に成功します!どのパターンもゼロ回一致できます。

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

  • [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

交互

以前、「ニック」または「ニック」のいずれかと一致する1つの方法を見ました。もう1つは、のように交互に使用する方法Nick|nickです。交替には、左側のすべてと右側のすべてが含まれることを覚えておいてください。範囲を制限するために括弧をグループ化する使用|例えば(Nick|nick)

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

脱出

一致する文字もあれば、特別な意味を持つ文字もあります。パターン\d+は、バックスラッシュ、小文字のD、プラス記号の順に一致しません。これを取得するには、を使用します\\d\+。バックスラッシュは、次の文字から特別な意味を取り除きます。

貪欲

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

たとえば、入力が

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

".+"「こんにちは」だけに一致することを期待しているかもしれませんが、「こんにちは」から「あなた」までずっと一致しているのを見ると驚かれることでしょう。

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

入力が「(123)(456)」の場合、最初のキャプチャは「123」になります。貪欲でない量指定子は、パターンの残りの部分ができるだけ早くマッチングを開始できるようにする必要があります。

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

アンカー

特別なパターン^を使用して、入力の最初$だけを照合し、最後だけを照合します。「表と裏に何があるかわかっているが、その間のすべてを私に与える」というあなたのパターンで「ブックエンド」を作成することは、便利なテクニックです。

フォームのコメントを照合したいとします

-- This is a comment --

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

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

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

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

無料のリソース

脚注

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


14
また、試行錯誤の方法を使用することができますし、オンライン正規表現テスターおよびデバッガを以下よりも大きな助けになります regex101.com
Juraj.Lorinc

2
似たようなパターンであるにもかかわらずa{,m}、少なくともJavascript、Perl、およびPythonでは、これは重要なことではありません。
モニカの訴訟に資金を提供

2
さまざまな種類の正規表現エンジンがあり、すべてに異なる機能セットと構文ルールがあることを言及することは非常に価値があります。
hek2mgl 2016年

1
hackr.io/tutorials/learn-regular-expressions-regexは、最高のオンライン正規表現チュートリアルを見つけるのに最適な場所です。ここでのすべてのチュートリアルは、プログラミングコミュニティによって提出され、推奨されています(SOのように支持されています)。
Saurabh Hooda 2017

2
一言ですべてをここに持ってくるためのあなたの努力に感謝します。
Saurabh Tiwari
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.