En utilisant PCRE, je souhaite capturer uniquement et tous les chiffres sur une seule ligne, mais uniquement si une certaine chaîne (disons "STRING99") est présente n'importe où dans cette ligne.
Par exemple, considérons ces deux cas:
a1 STRING99 2b c3d a1 2b c3d
Dans le premier cas, je veux que le résultat soit "19923". Dans le second cas, je veux un résultat vide.
Je ne suis pas sûr que cela soit possible. Cela peut fonctionner avec un look-back de longueur variable, mais cela n'est pas pris en charge dans PCRE. De plus, quelque chose comme (?=.*STRING99.*$)(\D|(\d))*
fonctionnera, mais "un groupe de capture répété ne capturera que la dernière itération", ce qui signifie que le deuxième groupe de capture ne capture que la dernière chiffre. Je ne parviens pas à trouver une solution de contournement pour cela.
(Ce n'est évidemment pas difficile à réaliser avec 2 opérations Regex consécutives, mais je le veux dans une formule.)
3 Réponses :
Nous pourrions utiliser un remplacement de regex avec une fonction de rappel:
$output = preg_replace_callback('/^.*\bSTRING99\b.*$/', function ($match) { return preg_replace("/\D+/", "", $match[0]); }, 'a1 STRING99 2b c3d'); echo $output; // prints 1992
L'approche ici consiste d'abord à faire correspondre uniquement les entrées contenant STRING 99
. Ensuite, sur une telle correspondance, nous supprimons tous les caractères non numériques. Les non-matches n'auraient pas ce remplacement effectué.
Je n'ai pas pu essayer cette méthode car je ne travaille pas réellement en PHP mais uniquement en utilisant PCRE dans Autohotkey. Merci, cependant, d'avoir proposé cette approche alternative.
Vous pouvez utiliser
(?:\G(?!^)|^(?=.*STRING99)|^.*(*ACCEPT))\d*\K\D+
Voir la démo regex (où j'ai remplacé \D
par [^\d\n]
à des fins de démonstration uniquement puisque le test est effectué sur une chaîne multiligne).
Détails
(?:\G(?!^)|^(?=.*STRING99)|^.*(*ACCEPT))
- soit la fin de la précédente correspondance réussie ( \G(?!^)
) Ou ( |
) la position de début de la chaîne si après n'importe quel 0+ caractères, il y a une chaîne STRING99
(voir ^(?=.*STRING99)
) ou (sinon) la chaîne entière correspond à ^.*
et la correspondance réussie est renvoyée (le modèle n'est pas analysé plus loin)\d*
- 0 chiffres ou plus sont consommés\K
- et supprimé de la mémoire tampon de correspondance\D+
- 1 ou plusieurs caractères non numériques (qui seront éventuellement supprimés).Merci! Cette solution semble également fonctionner correctement.
@Logitope Heureux que cela ait fonctionné pour vous. Veuillez également envisager de voter pour si ma réponse vous a été utile (voir Comment voter pour Stack Overflow? ), Car vous avez droit au privilège de vote positif après avoir atteint 15 points de répétition. Notez que vous pouvez voter pour toutes les réponses qui se sont avérées utiles.
Vous pouvez utiliser cette regex PCRE dans preg_replace
:
$repl = preg_replace('~^(?!.*STRING99).*(*SKIP)|\D+~', '', $str);
Détails RegEx:
^
: Démarrer(?!.*STRING99)
: Lokahead pour vérifier si nous avons STRING99
n'importe où en entrée.*(*SKIP)
: correspond au reste de l'entrée jusqu'à la fin et ignore-le|
: OU\D+
: correspond à 1+ sans chiffreCode PHP:
^(?!.*STRING99).*(*SKIP)|\D+
C'est une solution élégante. De plus (*SKIP)
serait omis.