回答:
最も重要な部分は概念です。ビルディングブロックがどのように機能するかを理解すると、構文の違いは穏やかな方言に過ぎません。正規表現エンジンの構文の上のレイヤーは、使用しているプログラミング言語の構文です。Perlなどの言語はこの複雑さのほとんどを取り除きますが、Cプログラムで正規表現を使用している場合は、他の考慮事項に留意する必要があります。
正規表現を自由に組み合わせて照合できる構成要素と考える場合は、独自のパターンを記述してデバッグする方法だけでなく、他の人が記述したパターンを理解する方法も学ぶことができます。
概念的には、最も単純な正規表現はリテラル文字です。パターンN
は文字「N」に一致します。
隣同士の正規表現はシーケンスを照合します。たとえば、パターンNick
は、「N」、「i」、「c」、「k」の順に一致します。
grep
Unixでこれまで使用したことがあれば、たとえ普通に見える文字列を検索するだけでも、すでに正規表現を使用していることになります。(re
in 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
すべてに一致します
最初の試合は重要な教訓を示しています。*
常に成功します!どのパターンもゼロ回一致できます。
他のいくつかの有用な例:
[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]
「任意の空白または任意の非空白」、つまり何でも一致するようなものを使用できます。
a{,m}
、少なくともJavascript、Perl、およびPythonでは、これは重要なことではありません。