web-dev-qa-db-fra.com

Qu'est-ce que la raison technique de "l'affirmation de l'apparence doit être une longueur fixe" dans Regex?

Par exemple, la regex ci-dessous provoquera une déclaration de défaillance l'assertion de l'apparence n'est pas une longueur fixe:

#(?<!(?:(?:src)|(?:href))=["\']?)((?:https?|ftp)://[^\s\'"<>()]+)#S

Un tel type de restriction n'existe pas pour lookahead.

44
wamp

Lookahead et lookbehind ne sont pas aussi semblables que leurs noms impliquent. L'expression Lookahead fonctionne exactement la même chose que si c'était une regex autonome, sauf qu'il est ancré à la position de match actuelle et qu'il ne consomme pas ce qu'il correspond.

Lookbehind est une histoire complète. En commençant par la position de match actuelle, il marche en arrière à travers le texte un caractère à la fois, essayant de faire correspondre son expression à chaque position. Dans les cas où aucun match n'est possible, le lookbehind doit aller jusqu'au début du texte (un personnage à la fois, rappelez-vous) avant d'abandonner. Comparez-la à l'expression de la lunette, qui est appliquée exactement une fois.

Il s'agit d'une simplification excessive brute, bien sûr, et toutes les saveurs ne fonctionnent pas de cette façon, mais vous obtenez l'idée. La façon dont regarder les regards est appliquée est fondamentalement différente de (et beaucoup, beaucoup moins efficace que), la façon dont les regards sont appliqués. Il suffit de mettre une limite sur la distance de dos à regarder.

72
Alan Moore

Tout d'abord, ce n'est pas vrai pour toutes les bibliothèques d'expression régulières (comme .NET).

Pour PCRE, la raison semble être:

La mise en œuvre des assertions de l'apparence est, pour chaque alternative, de ramener temporairement la position actuelle de la largeur fixe puis d'essayer de correspondre.

(au moins, selon http://www.autoitscript.com/autoit3/pcrepattern.html ).

11
mbeckish

PCRE ne prend pas en charge la photo flottante car elle peut entraîner des problèmes de performance majeurs. Ceci est dû à l'absence de capacité de correspondance droite à gauche: PCRE ne peut démarrer qu'une branche uniquement à gauche fixe, mais à gauche d'une looke de lectel de longueur variable ne peut pas être corrigée.

En règle générale, essayez de brancher la partie de votre lookequine à des modèles de longueur fixe si possible. Par exemple au lieu de:

(?<=(src|href)=")etc.

(1) utilisez ceci:

(?:(?<=src=")|(?<=href="))etc.

(2) Ou avec \K:

(src|href)="\Ketc.

Noter que \K N'EST PAS UNE REAL LOOKEQUETHIND, car elle commence toujours à la recherche à la fin de la correspondance précédente (aucun potentiel de retour potentiel dans le match précédent).

(3) Dans certains cas complexes, vous pouvez rechercher une expression "inversée" sur la lunette sur une chaîne inversée. Pas trop élégant mais ça marche:

.cte(?="=(ferh|crs))
6
Dávid Horváth

J'ai eu le même problème et l'a corrigé en utilisant (?: subexpression)

Définit un groupe non capturant. telle que Write(?:Line)? "writeine" dans "console.writine ()" "écrire" dans "console.write (valeur)"

Je devais changer la regex ci-dessous qui est supposée attraper avant , -o quelque chose dans le début de la chaîne qui me donnait l'affirmation de la recherche n'est pas une longueur fixe .

(?<=,|^)

avec ça,

(?:(?<=,)|^)
2
Mehrad
grep -P '(?<=((three)|(one)) )two' <<< "one two three three two one"
grep: lookbehind assertion is not fixed length

grep -P '((?<=(three) )|(?<=(one) ))two' <<< "one two three three two one"
one two three three two one

Pour le traitement de l'efficacité, PCRE ne prend pas en charge la correspondance ou la récursivité droite à gauche. Lorsque vous effectuez une recherche sur LookeBewind PCRE, la fin de toute chaîne correspondante précédente - Mise en œuvre des correspondances de taille variable nécessiterait une récursive et une réduction de l'efficacité. Voir: Regardez derrière des assertions

0
user4829160