高度な正規表現の後ろクルーシャル概念
正規表現(または、正規表現)トラバース大きな文字列に強力な手段注文情報を見つけるためにです。 彼らは、基になるパターンに文字列の構造内での魔法を動作するように頼っている。 残念なことに、単純な正規表現は複雑なパターンや記号に対処することはできません。 ジレンマこれにするには対処するには、 式を定期的にすることができます使用する高度な 。
以下では、我々は例の概念と使用される8つの一般的な紹介、導入を高度な正規表現。 各例では、単純な方法を複雑な文字列のパターンに一致するを説明します。 場合、式定期、基本的な経験をまだ持っているを見て、この記事開始を取得します。 構文は、ここで使用するPHPのPerl互換の正規表現にマッチします。
方法は[By、無料、フリーでした新しい場合は、ブランドを知っている我々はスマッシングメールニュースレター? 今すぐ登録を、新鮮な短いヒントと火曜日にトリックを入手!]
1。 欲張り/怠惰

すべての正規表現の繰り返し演算子は、 貪欲されます。 彼らは、できる限り文字列内の一致するようにしてください。 残念ながら、この可能性があります必ずしも望ましい効果があります。 したがって、遅延演算子は、この問題を解決するために使用されます。 彼らはただ最小パターンに一致する追加することによって使用される'?'は、 それぞれの貪欲な演算子の後。 また、'は、U'修飾子は、すべてのrepetiton演算子は怠け者するために使用されることがあります。 欲張りと怠惰の間の区別を完全な正規表現を理解する鍵となります。
貪欲演算子
*演算子は、0回以上前の式に一致します。 それは貪欲な子です。 次の式を考えます:
でpreg_match('/ <h1> .* <\ / h1という> /'、'これは見出しです<h1>。</ h1という> <h1>これは別の1つです。</ h1というの>'、$に一致);
ことを思い出して。 新しい行を除く任意の文字を意味します。 上記の正規表現は、h1タグとそのすべての内容を探している。 それが使用されます。 と*演算子は、常にタグの中にも一致する。 このパターンは一致します:
<h1>これは見出しです。</ h1という> <h1>これは別の1つです。</ h1という>
これは、文字列全体を返します。 *演算子は、継続的にすべてに一致します - も中間決算h1タグを - それは貪欲だからです。 文字列全体をマッチングできることは最適です。
レイジー演算子
のは、追加することによって、上記の演算子を変更してみましょう'?'は、 それ以降。 これは怠惰になる:
/ <h1> .*?<\ / h1という> /
正規表現は、その義務を果たすと、最初のh1タグにマッチします。 は(nこの同じプロパティを使用して別の貪欲な演算子)。 これは、前の式のn回以上にマッチします。 それは疑問符なしで使用されている場合、それはほとんどの繰り返しが可能探します。 それ以外の場合は、nの繰り返しから始まる:
文字列にstrに='ヒヒ'$を設定する#;#マッチは、)演算子にpreg_match(貪欲(nを使って'/(ハイテク)(1 ,}/', $ strは、$マッチ);#[0]はマッチします'ヒヒ'#マッチそれを怠惰(nで、)はできますか? 演算子でpreg_match('/(ハイテク)(1 ,}?/', $ strは、$マッチ);#'のハイテクされる[0]と一致する
2。 後方照応

それは何か
戻るを参照する式です定期的にする方法を参照して内部は、以前似たパターン。 たとえば、引用符で表現に一致する、この単純な正規表現を見てみましょう:
の配列を設定する#$は= array()でマッチを、#を作成する文字列に$ strを=""これは'文字列'\""れているå;#トラバースそれを正規表現にpreg_matchと("/(\"|') .*?(\ "|')/", $ strは、$に一致);#プリントは、全試合に、echo $ [0]と一致する。
残念ながら、この文字列を正しく一致しません。 その代わりに、印刷されます:
"これは'
この正規表現は開口部二重引用符と一致するが、引用のさまざまなタイプがそれを閉じると認めるとき。 それが最後に二重または単一引用符を選ぶのオプションを与えられたので、これが。 ためには、参照を戻すことができますこれを修正する。 式は\ 1、\ 2、...。、サブパターンは、以前撮影した参照を\ 9ホールド 。 最初に一致した見積り、この例では、変数で\ 1が開催されます。
どのようにそれを使用する
ために、前述の例では、この概念を適用する、最後の引用符の代わりに\ 1を使用する:
は、preg_match('/("| \ ').*? \ 1 /'、$ strは、$マッチ);
この意志が正しく戻り値:
"これは'文字列'です"#
参照を忘れないでは、その背中が使用されるもpreg_replace 。 その代わりに\ 1 ... \ 9は、使用する必要があります注意してください$ 1 ... $ 9 ... $で、n(これらの動作する任意の数の)。 たとえば、あなたが使用し、それらを表すテキストを持つすべての段落タグを置換する場合:
$テキスト= preg_replace('/ <P>この(.*?)< \ / pの> /'、"html)を$ $ 1 </ Pは>"を<P>この;
$ 1のバックリファレンスは、段落内のテキストを保持しているパターンそのものを交換に使用されています。 これは完全に有効な式は、簡単に交換しながらも似たパターンにアクセスする方法を示します。
3。 名前付きグループ
使用して複数のバックリファレンスは、正規表現をすばやく混乱と理解しにくいとなることができますが。 別の方法で参照をバックアップするグループの名前使用しているし。 名前のグループが使用して指定されて(?P<name>pattern)はパターンの名前ですグループ自体のグループ表現される正規。 グループはその後によって(参照できますか?P =名)。 たとえば、次の検討:
/に(?P <quote> "|').*?(? P =引用符)/
上記の式は、以前の後方参照の例と同じ効果を作成するのではなく名前付きグループを使用します。 また、大幅に読みやすくなります。
名前付きグループはまた、時の配列をふるいにかける便利ですしています。 名前が特定のパターンに与えられるも対応のキー配列をしています。
は、preg_match('/に(?P <quote>は"\ ')/',は"'文字列'"、$に一致);#これは"'"エコードルを印刷する[1]と一致する。#これはまた、"'"印刷されます表示| 、それは名前のグループですエコー$は、['引用符']と一致する。
したがって、コードだけを読みやすくがすることはまた、それを整理するグループの名前。
4。 ワード境界

単語の境界は、文字の単語-非され、文字の場所で文字列来ると単語。 これらの境界の専門彼らは実際に文字が一致しないという事実である。 その長さはゼロです。 \ \b表現の境界に一致する単語。
残念ながら、境界線は頻繁に多くの人が彼らの本当の意義を認識していない以上ざっとです。 たとえば、あなたは"言葉"インポートと一致するとしましょう:
/インポート/
危ない!/気を付けて! 正規表現は難しいことができます。 上記の式もマッチします:
重要な
あなたはそれは前にスペースを追加し、インポート後に、これらの偽を防ぐために同じくらい簡単ですと思うかもしれません一致:
/インポート/
しかし、この場合、どうですか?
トレーダーは、インポートのための投票
インポートの先頭または文字列の終わりには、変更された正規表現は失敗します。 したがって、これをケースに分割が必要です:
/(^輸入|輸入|輸入ドル)/私は
戻って我々の正規表現を見て、それは期間またはアカウントに他の句読点を取ることはありません。 ちょうどこのように見えるかもしれません、この1つの単語を、正規表現と一致する:
/(^輸入(:|;|,)? |のインポート|インポート(\ (:|;|,)?。| \ ?|!)?$)/私
それは多くのコードだけで1つの単語に一致することです。 これはなぜ単語の境界はとても重要です。 境界の単語に達成する上、他のバリエーションを多くのステートメントと、すべてのことが必要です:
/ \ bimport \ bを/
これは、詳細が一致するすべての場合、上記と\b 'の柔軟性は、文字列の長さのゼロ来るから事実と一致する。 それが一致するすべての2つの文字の間に虚空間です。 これは、1つの文字の場合、非単語文字、もう一方が単語文字がチェックされます。 もしそうなら、それをしています。 が発生した場合の先頭、あるいは最後に文字列は、 \ \bの-扱いますそれを非。 ため、私iインポートが文字の単語も考え、それがインポートにマッチします。
その\ bの反対\ Bの注意してください この演算子はスペースにマッチします内の間に2つの単語または2つの非単語文字。 あなたは'別の単語内のハイテクに合わせてご希望の場合したがって、あなたが使うことができます:
\ Bhi \ Bの
5。 原子グループ

原子グループがキャプチャされる非特別な正規表現のグループ。 彼らは通常、正規表現の効率を高めるために、使用されますがまた、適用される可能性があります特定の試合を排除します。 原子グループは(使用して指定ですか?>パターン):
/(?彼|>この)/
とき正規表現エンジンは原子グループに一致する、それが内のすべてのトークンに付属してポジションをbacktracting破棄されます。 考えて言葉スマッシング'。 上記の正規表現を使用して、正規表現エンジンは最初のパターンを'一致するようにしようとする彼の'でスマッシング'。 それはマッチを見つけることはありません。 この時点で、原子団は、エンジンインチすべてのバックトラックの位置を破棄しますキックされます。 これは、これは'の内部'破壊を検索できないことを意味します。 なぜですか? 'もし彼の'し、明らかに'一致する回答は得られなかったこの'(これは彼の')正のいずれかが返されません含まれています。
上記の例では、多くの実用的な用途を持っていなかった。 我々は、使用可能性がありますようにしても/t?his?/代わりに。 次のを見て:
/ \ b()\ bを彫り込む|最後を表示|エンジニアリング/
正規表現エンジンは、単語のエンジニアリング'指定された場合、それは正しく'にマッチしますエンジニア'。 次の単語の境界は、\ b、一致しません。 したがって、次の一致:彫り込むに移動します。 これは、'eng'にマッチが、実現の残りはありません。 最後に、'end'のは、試行されるも失敗しました。 あなたは慎重に見ている場合は、エンジンのエンジニア'と最後の単語の境界を失敗と一致する1回、それはおそらく'彫り込むまたは'end'の一致しないことを認識します。 これら2つの'よりもエンジニアが'、つまり正規表現エンジン他の試験を続行しないでください小さい単語が一致します。
/ \ b(?>エンジニア|彫り込む|エンド)\ b /
上記の正規表現エンジンの時間を節約し、コードの効率を改善するより良い代替手段です。
6。 再帰

再帰は、式の中で定期的に、タグのHTML、構造入れ子に一致することができます使用することなど、かっこ、(この(その))、および<div></div> 。 彼らの使用を必要とする(?R)パターンをサブ演算子と一致する再帰的。 ネストされた括弧にマッチする正規表現を考えてみましょう:
/ \ (((?>[^()]+)|(?研究))* \)/
この正規表現の一番外側の括弧は入れ子になったの先頭に一致する構造。 次に、(非括弧文字だと一致するかのオプション演算子は、することができます?>[^()]+の?>[^()]+パターン)を再度式全体を(?R)は。 注意この演算子が繰り返される可能な限り、すべてのネストした括弧に一致するように何度も。
仕事で再帰のもう一つの例では、以下の通りです:
/((?>[^]+)|((?研究)))*/
上記の式は、ネストされたタグに一致する文字グループ、貪欲な演算子、バックトラッキング、原子グループを組み合わせたものです。 最初の括弧で囲まれたグループは、([\ w]の+)が後で使用するための正規表現でタグ名に一致します。 それは、タグの残りの部分と一致するよう進みます。 次の括弧で囲まれたサブ式は非常に上記のいずれかに似ています。 これは、いずれか別のタグ(以上非タグ(?>[^]+)文字または再帰的に一致する?R)の。 最後に、式の最後の部分は終了タグにマッチします。
7。 コールバック

特定のパターンに特殊な変更を必要とする可能性がありますしています。 ために使用される変更を、 コールバックができるに適用される複雑なまたは複数の。 コールバックにダイナミックな使用される文字列の置換preg_replace_callback関数preg_replace_callback
彼らは、パラメータとしてときに一致が見つかった場合に使用する機能をお楽しみください。 この関数は、パラメータとしてマッチ配列を受信し、代替品として使用されて変更した文字列を返します。
例として、すべての単語を指定した文字列に大文字に変更する正規表現を考える。 残念なことに、PHPは異なる場合に文字を変更する正規表現演算子を持っていません。 このタスクを実行するには、コールバックを使用することがあります。 まず、式は大文字する必要があるすべての文字に一致する必要があります:
/ \ b \ wは/
上記は動作するように両方の単語の境界と文字クラスを使用します。 今、私たちはこの顔をして、我々はコールバック関数を書くことができます:
関数メッセージ。は、($と一致する)(戻りstrtoupper($と一致する[0]);)
upper_case一致の配列を受け取り、大文字全体マッチしたパターンをで返します。ドル$matches[0]で、大文字にすることを表す必要がある文字を。 すべてを使用して、これは一緒に置くことがすぐにできますpreg_replace_callback preg_replace_callbackを:
の、preg_replace_callback('/ \ b \ wは/'、"MSGメッセージ"、$ str)と;
それは単純なコールバックの力である。
8。 注釈

注釈文字列を一致されていない、実際にする方法、それは表現される正規の最も重要な部分の1つです。 が大きいほど、より複雑な式は、それが何なのか実際にマッチされている解読になるには、深く潜るように。 正規表現の中にコメントを使用して最適な方法などの混乱を最小限に抑えるためです。
式定期的に内部にコメントをするには配置すると、使用して(?コメント(?#comment)
お好みの単語(秒)を置き換えます"コメント":
/(?#桁)\ d /に
これは特に重要なのは一般に公開正規表現をコメントすることです。 あなたの正規のユーザーが簡単に理解し、パターンを自分のニーズに合わせて変更できるようになります。 するときにプログラムを見直すことをデコードするためにはそれもこれまで行くことができます。
の使用を検討"x"または(?x)はコメントフリー間隔モードの修飾子。 これは、正規表現をトークン間の空白を無視します。 すべてのスペースはとすることができます表されるも[ ]や\ (バックスラッシュとスペース):
/ \ dは#桁[]の#スペース\は+#単語wを/ xの
上記と同じです:
/ \ dは(?#桁)[](?#スペース)\ワットのメッセージ+(?#ワード)/
常に十分に文書化コードを作成します。
さらにリソース
- 正規Expressions.info
正規表現の総合サイト - カンニングペーパー
有益な正規表現は、カンニングペーパー - 正規表現ジェネレータ
JavaScriptの正規表現ジェネレータ
(アル)
