Maison  >  Article  >  interface Web  >  Efficacité de l'utilisation des expressions régulières en PHP Explication détaillée des expressions gourmandes, non gourmandes et backtracking (avec code)

Efficacité de l'utilisation des expressions régulières en PHP Explication détaillée des expressions gourmandes, non gourmandes et backtracking (avec code)

php中世界最好的语言
php中世界最好的语言original
2018-03-30 10:51:551400parcourir

Cette fois, je vais vous apporter une explication détaillée de l'efficacité gourmande, non gourmande et du backtracking de l'utilisation de la régularité en PHP (avec code Remarques sur l'utilisation de la régularité en efficacité gourmande, non gourmande et du backtracking en PHP). De quoi s’agit-il ? Voici des cas concrets.

Tout d'abord, apprenons ce qu'est la gourmandise des expressions régulières et qu'est-ce que la non-gourmandise ? Ou qu'est-ce qu'un quantificateur de priorité correspondant et qu'est-ce qu'un quantificateur de priorité ignorant ?

D’accord, je ne sais pas quel est le concept. Donnons un exemple.

Un étudiant a voulu filtrer le contenu entre eux. C'est ainsi qu'il a rédigé les règles et procédures habituelles.

$str = preg_replace('%<script>.+?</script>%i','',$str);//非贪婪

Il semble qu'il n'y ait rien de mal à cela, mais en fait ce n'est pas le cas. Si

$str = '<script<script>alert(document.cookie)</script>>alert(document.cookie)</script>';

, alors après la procédure ci-dessus, le résultat est

$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>

qui ne peut toujours pas obtenir l'effet souhaité. Ce qui précède n'est pas de la cupidité, et certains sont appelés paresse. Le signe du non gourmand est la quantité métacaractère suivi de ?, comme +?, *?, ?? (plus spécial, j'en parlerai dans les prochains blogs), etc. Autrement dit, cela signifie non gourmand. Si vous n'écrivez pas ?, cela signifie gourmand. Par exemple,

$str = '<script<script>alert(document.cookie)</script>>alert(document.cookie)</script>'; 
$str = preg_replace('%<script>.+</script>%i','',$str);//非贪婪 
print_r($str); 
//$str 输出为 

Ce qui précède est une introduction à la différence entre gourmand et non gourmand. Parlons ensuite des problèmes de retour en arrière causés par la cupidité et la non-cupidité. Regardons d’abord un petit exemple.

L'expression régulière est w*(d+), et la chaîne est cfc456n Alors, quel est le 1 $ de cette correspondance régulière ? ?

Si votre réponse est 456, alors félicitations, votre réponse est fausse. Le résultat n'est pas 456, mais 6. Savez-vous pourquoi ?

CFC4N expliquera. Lorsque le moteur standard utilise w*(d+) régulier pour correspondre à la chaîne cfc456n, il utilisera d'abord w* pour correspondre à la chaîne cfc456n. Tout d'abord, w* correspondra à toute la chaîne cfc456n. caractères, puis remettez-le à d+ pour qu'il corresponde à la chaîne restante, et le reste a disparu à ce moment-là, la règle w* crachera à contrecœur un caractère pour que d+ corresponde en même temps, avant de cracher le caractère. , enregistrez un point, ce point est le point utilisé pour le retour en arrière. Ensuite, d+ correspond à n et constate que la correspondance ne peut pas réussir. Il demandera à nouveau à w* de cracher un autre caractère. w* enregistrera d'abord un point de retour en arrière, puis crachera. sortir un personnage. À l'heure actuelle, le résultat de la correspondance de w* n'est que cfc45, et 6n a été craché à nouveau, d+ correspond à 6. S'il constate que la correspondance est réussie, le moteur sera informé que la correspondance est réussie, et ce sera le cas. affiché directement. Par conséquent, le résultat de (d+) est 6 et non 456.

Lorsque l'expression régulière ci-dessus est modifiée en w*?(d+) (notez qu'elle n'est pas gourmande ici), la chaîne est toujours cfc456n. Alors, à ce moment, quelle est la correspondance régulière $1 ? ?

L'étudiant A a répondu : Le résultat est 456.

Eh bien, oui, c'est exact, c'est 456. CFC4N aimerait demander, pourquoi est-ce 456 ?

Laissez-moi vous expliquer pourquoi il s'agit de 456

Il existe une règle dans les expressions régulières selon laquelle les quantificateurs correspondent en premier, donc w* correspondra en premier à la chaîne cfc456, car w* n'est pas gourmand ? , le moteur standard utilisera l'expression w+? pour faire correspondre une seule chaîne à la fois, puis transférera le contrôle au d+ suivant pour faire correspondre le caractère suivant. En même temps, il enregistrera un point pour revenir ici lorsque la correspondance est terminée. échec, correspond à nouveau, ce qui est le point de retour en arrière. Puisque w est suivi du quantificateur *, * représente 0 à un nombre incalculable de fois, donc le premier est 0 fois, c'est-à-dire que w*? correspond à une valeur nulle, enregistre le point de traçage et confie le contrôle à d+, d+ correspond au premier de cfc456n Caractère c, alors la correspondance échoue, alors le contrôle est confié à w*? pour correspondre au c de cfc456n, w*? correspond à c avec succès, car il n'est pas gourmand, donc il ne correspond qu'à un seul caractère à un moment et enregistre le point de retraçage, puis donne le contrôle à d+ pour correspondre à f. Ensuite, d+ ne parvient pas à correspondre à nouveau à f, puis donne le contrôle à w*?, w*? correspond ensuite à c et enregistre le point de retraçage (à cette fois, le résultat de la correspondance de w*? est cfc ), puis donnez le contrôle à d+, d+ correspond à 4, et la correspondance est réussie. Ensuite, puisque le quantificateur est +, il est de 1 à un nombre incalculable de fois, donc il correspond plus tard. , puis correspond à 5, et il réussit, puis correspond à nouveau à 6. En cas de succès, continuez l'opération de correspondance. Le caractère suivant est n et la correspondance échoue à ce moment-là, d+ cèdera le contrôle. Puisqu'il n'y a pas d'expression régulière après d+, l'expression régulière entière est déclarée comme étant correspondante et le résultat est cfc456, dont le premier ensemble de résultats est 456. Cher camarade de classe, comprenez-vous le résultat de la question à l'instant, pourquoi est-ce 456 ?

D'accord, avez-vous compris les principes de correspondance gourmande et non gourmande à partir de l'exemple ci-dessus ? Comprenez-vous quand vous devez utiliser gourmand ou non gourmand pour traiter votre chaîne ?

L'article de Niao Ge mentionnait que pour les expressions et les programmes,

$reg = "/<script>.*?<\/script>/is"; 
$str = "<script>********</script>"; //长度大于100014 
$ret = preg_repalce($reg, "", $str); //返回NULL

La raison est qu'il y a trop de backtraces, jusqu'à ce que l'espace de la pile soit épuisé et que la pile explose.

再来看个例子。

字符串

$str = '<script>123456</script>';

正则表达式为

$strRegex1 = '%<script>.+<\/script>%'; 
$strRegex2 = '%<script>.+?<\/script>%'; 
$strRegex3 = '%<script>(?:(?!<\/script>).)+<\/script>%';

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

推荐阅读:

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

正则的位置匹配使用详解

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn