763 votes

Expression régulière qui s'arrête à la première correspondance

Mon modèle de regex ressemble à quelque chose comme

<xxxx location="file path/level1/level2" xxxx some="xxx">

Je ne suis intéressé que par la partie entre guillemets affectée à l'emplacement. Cela ne devrait-il pas être aussi simple que ci-dessous sans le commutateur gourmand ?

/.*location="(.*)".*/

Cela ne semble pas fonctionner.

0 votes

Quelle est votre source, est-ce du HTML, du xml ou autre ?

26 votes

Pourquoi est-ce un wiki communautaire ? C'est une vraie question. Trop tard maintenant.

1 votes

Dans quelle langue écrivez-vous ? N'utilisez pas de regex pour le XML. Il y a tellement de meilleures façons d'analyser le XML.

3voto

Ste Points 732

Voici un autre moyen.

Voici celui que vous voulez. C'est paresseux [\s\S]*?

Le premier point : [\s\S]*?(?:location="[^"]*")[\s\S]* Remplacer par : $1

Explication : https://regex101.com/r/ZcqcUm/2


Pour être complet, il faut que ce soit le dernier. C'est gourmand [\s\S]*

Le dernier point : [\s\S]*(?:location="([^"]*)")[\s\S]* Remplacer par : $1

Explication : https://regex101.com/r/LXSPDp/3


Il n'y a qu'une seule différence entre ces deux expressions régulières et c'est la ?

3voto

tripleee Points 28746

Les autres réponses ne proposent pas de solution complète pour les versions de regex qui ne prennent pas en charge la correspondance non avide. Les quantificateurs gourmands ( .*? , .+? etc) sont une extension de Perl 5 qui n'est pas prise en charge par les expressions régulières traditionnelles.

Si votre condition d'arrêt est un seul caractère, la solution est simple : au lieu de

a(.*?)b

vous pouvez correspondre

a[^ab]*b

c'est-à-dire spécifier une classe de caractères qui exclut les délimiteurs de début et de fin.

Dans le cas plus général, vous pouvez minutieusement construire une expression comme

start(|[^e]|e(|[^n]|n(|[^d])))end

pour capturer une correspondance entre start et la première occurrence de end . Remarquez comment la sous-expression avec des parenthèses imbriquées présente un certain nombre d'alternatives qui permettent entre elles e seulement s'il n'est pas suivi par nd et ainsi de suite, en prenant soin de couvrir la chaîne vide comme une alternative qui ne correspond pas à ce qui est interdit à ce moment précis.

Bien sûr, l'approche correcte dans la plupart des cas est d'utiliser un analyseur approprié pour le format que vous essayez d'analyser, mais parfois, il se peut qu'il n'y en ait pas, ou que l'outil spécialisé que vous utilisez insiste sur une expression régulière et rien d'autre.

2voto

Mohammad Kanan Points 2639

Parce que vous utilisez sous-modèle quantifié et comme décrit dans Doc Perl ,

Par défaut, un sous-modèle quantifié est " gourmand "c'est-à-dire qu'il correspondra à plusieurs fois que possible (compte tenu d'un emplacement de départ particulier) tout en permettant au reste du motif de correspondre. Si vous voulez pour correspondre au nombre minimum de fois si possible, suivez le quantificateur avec a " ?" . Notez que les significations ne changent pas, seulement la "cupidité". "gourmandise" :

*?        //Match 0 or more times, not greedily (minimum matches)
+?        //Match 1 or more times, not greedily

Ainsi, pour permettre à votre quantifié pour obtenir une correspondance minimale, suivi par ? :

/location="(.*?)"/

0voto

user13202738 Points 39
import regex
text = 'ask her to call Mary back when she comes back'                           
p = r'(?i)(?s)call(.*?)back'
for match in regex.finditer(p, str(text)):
    print (match.group(1))

Sortie : Mary

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X