ホームページ >バックエンド開発 >PHPチュートリアル >phpは入れ子になった括弧内のテキストと一致します

phpは入れ子になった括弧内のテキストと一致します

WBOY
WBOYオリジナル
2016-06-13 13:08:21754ブラウズ

phpは入れ子になった括弧内のテキストと一致します

この記事の内容は、インターネットの記事「PHP 正規表現の細かい点」から編集されたもので、分析プロセスが非常に詳細に記載されており、PHP の正規表現の一般的な機能を抜粋したものです。再帰部分を翻訳して整理しました。

以前の記事では、Perl 言語の再帰正規表現を翻訳しましたが、実際には、この記事で紹介する PHP 正規表現のように、多くの言語の正規表現が再帰をサポートしています。それらはすべて「規則的」であり、問​​題の 85% 以上は最も基本的な文法だけで解決できます。複雑な問題を解決するために共通の規則性を合理的かつ効果的に使用することもスキルと知識ですが、より高度な文法です。確かにその価値はありますが、それなしでは物事を成し遂げることができないこともあります。また、規則的なルールを学ぶことの楽しみは、さまざまな可能性を試して、無限の好奇心を満足させることです。

この記事の内容は、インターネットの記事「PHP 正規表現の細かい点」から編集されたもので、分析プロセスが非常に詳細に記載されており、PHP の正規表現の一般的な機能を抜粋したものです。再帰部分を翻訳して整理しました。

テキスト

再帰正規表現はどのような場合に使用されますか? もちろん、それは、一致する文字列内に特定のパターンが再帰的に出現する場合です (一見ナンセンスです)。入れ子の括弧の再帰的正規処理の問題
の例は次のとおりです。
テキストに正しくペアになったネストされた括弧が含まれているとします。そのような括弧グループをキャプチャしたいとします。
ネタバレをお許しください。標準的な答えは次のとおりです:

ソースプリントを表示しますか?
1 <?php?

2 <span style="color: #aa7700;">$string</span> = <span style="color: #0000ff;">"some text (a(b(c)d)e) more text"</span>;?

3 <strong><span style="color: #006699;">if</span></strong>(preg_match(<span style="color: #0000ff;">"/(([^()]+|(?R))*)/"</span>,<span style="color: #aa7700;">$string</span>,<span style="color: #aa7700;">$matches</span>))?

4 {?

5 <span style="color: #ff1493;">echo</span> <span style="color: #0000ff;">"<pre class="brush:php;toolbar:false">&quot;&lt;/code&gt;&lt;code class=&quot;php plain&quot;&gt;; print_r(&lt;/code&gt;&lt;code class=&quot;php variable&quot;&gt;&lt;span style=&quot;color: #aa7700;&quot;&gt;$matches&lt;/span&gt;&lt;/code&gt;&lt;code class=&quot;php plain&quot;&gt;); &lt;/code&gt;&lt;code class=&quot;php functions&quot;&gt;&lt;span style=&quot;color: #ff1493;&quot;&gt;echo&lt;/span&gt;&lt;/code&gt; &lt;code class=&quot;php string&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;</pre>"</span>;?
6 }?
7 ?>
出力結果は次のとおりです:

ソースプリントを表示しますか?
1 Array?
2 (?
5 )

必要なテキストが $matches[0] にキャプチャされていることがわかります。

原理

次に原理
について考えてみましょう。

上記の正規表現の重要な点は (?R) です。(?R) の機能は、反復ごとに、その正規表現全体を再帰的に置き換えることです。 ) ?R) は「(([^()]+|(?R))*)」に置き換えられます。

したがって、特に上記の例の場合、正規表現は次と同等です:

"/(([^()]+|(([^()]+|(([^()]+)*))*))*)/"

ただし、上記のコードは、深さが 3 レベルの括弧にのみ適しています。深さが不明な括弧のネストの場合は、次の通常のパターンを使用する必要があります。

"/(([^()]+|(?R))*)/"

無制限の深さで照合できるだけでなく、正規表現の構文も簡素化されます。

次に、「/(([^()]+|(?R))*)/」が「(a(b(c)d)e)」とどのように一致するかを詳しく見てみましょう。

「(c)」の部分は正規表現「(([^()]+)*)」で一致しますが、(c) は実際には再帰全体の縮図に相当します。

つまり、次のステップの (c) は (?R) を使用して照合できます。 b(c)d) は次のとおりです:

" ("match"(";
"[^()]+"match "b";
(?R)match "(c)";
"[^()]+"match" d";
")"match")".
上記の一致原理によれば、2 番目の要素が $matches[1] である理由を理解するのは難しくありません。 ] 配列の部分文字列 'e' は、最後の一致反復でキャプチャされ、最後のキャプチャ結果のみが配列に保存されます。
rex 注: この機能については、自分で試して、文字列 abc123xyz890 と一致する正規表現 ([a-z]+[0-9]+)+ を使用して $1 がキャプチャされた結果を確認することができます。これは左最長原則と矛盾しません。
$matches[0] のみをキャプチャする必要がある場合は、次のようにすることができます:

ソースプリントを表示しますか?

1 <?php?

2 <span style="color: #aa7700;">$string</span> = <span style="color: #0000ff;">"some text (a(b(c)d)e) more text"</span>;?

3 <strong><span style="color: #006699;">if</span></strong>(preg_match(<span style="color: #0000ff;">"/((?:[^()]+|(?R))*)/"</span>,<span style="color: #aa7700;">$string</span>,<span style="color: #aa7700;">$matches</span>))?

4 {?

5 <span style="color: #ff1493;">echo</span> <span style="color: #0000ff;">"<pre class="brush:php;toolbar:false">&quot;&lt;/code&gt;&lt;code class=&quot;php plain&quot;&gt;; print_r(&lt;/code&gt;&lt;code class=&quot;php variable&quot;&gt;&lt;span style=&quot;color: #aa7700;&quot;&gt;$matches&lt;/span&gt;&lt;/code&gt;&lt;code class=&quot;php plain&quot;&gt;); &lt;/code&gt;&lt;code class=&quot;php functions&quot;&gt;&lt;span style=&quot;color: #ff1493;&quot;&gt;echo&lt;/span&gt;&lt;/code&gt; &lt;code class=&quot;php string&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;</pre>"</span>;?
6 }?
7 ?>
は同じ結果を生成します:

ソースプリントを表示しますか?

1 Array?
4 )

変更点は、捕捉括弧 () が非捕捉捕捉括弧 (?:) に変更されたことです。

はさらに次のように改良できます:

?

ソースプリントを表示しますか?
1 <?php?

2 <span style="color: #aa7700;">$string</span> = <span style="color: #0000ff;">"some text (a(b(c)d)e) more text"</span>;?

3 <strong><span style="color: #006699;">if</span></strong>(preg_match("/((?>[^()]+|(?R))*)/",<span style="color: #aa7700;">$string</span>,<span style="color: #aa7700;">$matches</span>))?
4 {?
5 <span style="color: #ff1493;">echo</span> <span style="color: #0000ff;">"<pre class="brush:php;toolbar:false">&quot;&lt;/span&gt;&lt;/code&gt;&lt;code class=&quot;php plain&quot;&gt;; print_r(&lt;/code&gt;&lt;code class=&quot;php variable&quot;&gt;&lt;span style=&quot;color: #aa7700;&quot;&gt;$matches&lt;/span&gt;&lt;/code&gt;&lt;code class=&quot;php plain&quot;&gt;); &lt;/code&gt;&lt;code class=&quot;php functions&quot;&gt;&lt;span style=&quot;color: #ff1493;&quot;&gt;echo&lt;/span&gt;&lt;/code&gt; &lt;code class=&quot;php string&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;</pre>"</span>;?
6 }?
7 ?>
ここでは、いわゆるワンタイム モードを使用します (rex 注: Yu Sheng 氏が翻訳した「Mastering Regular Expressions v3.0」では、これは「固定化グループ化」と呼ばれています。書籍を参照してください)。 PHP マニュアルでは、正規表現の速度を向上させるために、If 条件が許す限り、できるだけこのモードを使用することを推奨しています。

ワンタイム モードは非常に簡単なので、ここでは詳しく説明しません。興味がある場合は、公式の PHP マニュアルを参照してください。PERL 互換の正規表現について詳しく知りたい場合は、を参照してください。記事の最後にあるリンク

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。