ホームページ > ウェブフロントエンド > jsチュートリアル > PHP での正規表現の使用効率化 貪欲、非貪欲、バックトラッキングの詳細な説明 (コード付き)

PHP での正規表現の使用効率化 貪欲、非貪欲、バックトラッキングの詳細な説明 (コード付き)

php中世界最好的语言
リリース: 2018-03-30 10:51:55
オリジナル
1449 人が閲覧しました

今回は、PHP で通常の貪欲、非貪欲、およびバックトラッキングを使用する効率について詳しく説明します (コード付き) 注意点とは何か、そして以下は実際の戦闘です ケースを見てみましょう。 。

まず、正規表現における貪欲性について学びましょう。また、非貪欲性とは何でしょうか?あるいは、何が優先量指定子と一致し、何が優先量指定子を無視するのでしょうか?

わかりました、概念が何なのかわからないので、例を挙げてみましょう。

ある学生は、コンテンツをフィルタリングしたいと考え、通常のルールと手順をこのように書きました。

$str = preg_replace('%<script>.+?</script>%i','',$str);//非贪婪
ログイン後にコピー

何も問題がないように見えますが、実際はそうではありません。

$str = '<script<script>alert(document.cookie)</script>>alert(document.cookie)</script>';
ログイン後にコピー

の場合、上記のプログラム処理後の結果は

$str = '<script<script>alert(document.cookie)</script>>alert(document.cookie)</script>'; 
$str = preg_replace('%<script>.+?</script>%i','',$str);//非贪婪 
print_r($str); 
//$str 输出为 <script>alert(document.cookie)</script>
ログイン後にコピー

ですが、それでも期待する効果を達成できません。上記は貪欲ではなく、怠惰と呼ばれるものもあります。貪欲でない記号は、+?、*?、?? などの、数量 メタキャラクター の後に ? が続きます (さらに特別なものについては、今後のブログで書きます)。 ?を書かない場合は貪欲を意味します。例えば

$str = '<script<script>alert(document.cookie)</script>>alert(document.cookie)</script>'; 
$str = preg_replace('%<script>.+</script>%i','',$str);//非贪婪 
print_r($str); 
//$str 输出为 
ログイン後にコピー

上記は貪欲と非貪欲の違いの紹介です。次に、貪欲と非貪欲によって引き起こされる後戻りの問題について話しましょう。まずは小さな例を見てみましょう。

正規表現は w*(d+)、Stringは cfc456n では、この正規表現に一致する $1 は何でしょうか? ?

答えが 456 の場合、おめでとうございます。結果は 456 ではなく、6 です。理由はわかりますか?

CFC4N が説明します。通常のエンジンが文字列 cfc456n と一致させるために通常の w*(d+) を使用する場合、最初に w* を使用して文字列 cfc456n と一致し、次に w* が文字列 cfc456n と一致します。残りの文字列と一致するように d+ に任せると、残りはなくなります。このとき、w* ルールは、d+ が一致する文字を吐き出すと同時に、文字を吐き出す前にポイントを記録します。この point はバックトラッキングに使用されるポイントであり、その後 d+ は n と一致します。一致が成功しないことが判明した場合は、w* に別の文字を吐き出すよう再度要求し、最初にバックトラッキング ポイントを記録します。それから文字を吐き出します。このとき、w* のマッチング結果は cfc45 のみで、再度 6n が吐き出され、マッチングが成功したことが判明するとエンジンにマッチング成功が通知されます。直接表示されます。したがって、(d+) の結果は 456 ではなく 6 になります。

上記の正規表現を w*?(d+) に変更しても (ここでは非貪欲であることに注意してください)、文字列は cfc456n のままです。では、この時点での正規一致 $1 は何でしょうか? ?

生徒 A は答えました: 結果は 456 です。

そうですね、そうです、456 です。CFC4N が聞きたいのですが、なぜ 456 なのでしょうか?

なぜ 456 なのかを説明します

正規表現には量指定子が最初に一致するという規則があるため、w*? は文字列 cfc456 に最初に一致します。エンジンは式 w+ を使用します。一度に 1 つの文字列のみに一致し、次の文字に一致するように制御を後続の d+ に渡します。同時に、一致が失敗した場合にここに戻り、再度一致するためのポイントが記録されます。それが後戻りのポイントです。 w の後に量指定子 * が続くため、* は 0 から数え切れないほどの回数を表すため、最初は 0 回です。つまり、w*? は null に一致し、トレースバック ポイントを記録し、制御を d+ に渡します。d+ は次の最初のものと一致します。 cfc456n 文字 c の場合、マッチングは失敗するため、制御は cfc456n の c と一致するように w*? に渡されます。w*? は貪欲ではないため、一度に 1 文字のみと一致します。そして、トレースバック ポイントを記録し、次に f と一致するように d+ に制御を渡します。その後、d+ は再び f と一致しませんでした。その後、制御を w*? に渡し、次に c と一致し、トレースバック ポイントを記録します (この時点では)。 、 w*? のマッチング結果は cfc )、そして d+ に制御を渡し、 d+ は 4 と一致し、一致は成功します。 そして、量指定子が + であるため、数え切れないほど後で一致します。次に 5 に一致すると成功し、次に 6 に一致すると、次の文字が n になり、この時点でマッチングは失敗します。 d+ の後に正規表現がないため、正規表現全体が一致すると宣言され、結果は cfc456 となり、そのうちの最初の結果セットは 456 です。クラスメートの皆さん、今の質問の結果はわかりましたか、なぜ 456 なのか?

さて、上記の例から、貪欲なマッチングと非貪欲なマッチングの原則を理解できましたか?文字列を処理するためにグリーディまたは非グリーディを使用する必要がある場合を理解していますか?

Niao 兄弟の記事では式とプログラムについて

$reg = "/<script>.*?<\/script>/is"; 
$str = "<script>********</script>"; //长度大于100014 
$ret = preg_repalce($reg, "", $str); //返回NULL
ログイン後にコピー
として説明しています

その理由は、スタック領域が使い果たされてスタックが爆発するまでバックトレースが多すぎるためです。

再来看个例子。

字符串

$str = '<script>123456</script>';
ログイン後にコピー

正则表达式为

$strRegex1 = '%<script>.+<\/script>%'; 
$strRegex2 = '%<script>.+?<\/script>%'; 
$strRegex3 = '%<script>(?:(?!<\/script>).)+<\/script>%';
ログイン後にコピー

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

用正则匹配单个字符的详细解析

正则的位置匹配使用详解

以上がPHP での正規表現の使用効率化 貪欲、非貪欲、バックトラッキングの詳細な説明 (コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート