Expression régulière pour s'arrêter au premier match

532

Mon motif d'expression régulière ressemble à quelque chose comme

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

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

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

Ne semble pas fonctionner.

publicRavi
la source
Quelle est votre source, est-ce HTML ou xml ou quelque chose?
Oskar Kjellin
20
Pourquoi est-ce un wiki communautaire? C'est une vraie question. Trop tard maintenant.
Ahmad Mageed
1
Dans quelle langue écrivez-vous? Veuillez ne pas utiliser l'expression régulière pour XML. Il y a tellement de meilleures façons d'analyser XML
Oskar Kjellin
3
Pas si tout ce que vous voulez est de rechercher des attributs simples. Regex est approprié et plus rapide.
codenheim
Je dirais que si vous par exemple du code c # il est tellement préférable d'utiliser linq pour cela. Je doute qu'il sera préférable de regex si vous avez un bon analyseur
Oskar Kjellin

Réponses:

1097

Vous devez rendre votre expression régulière non gourmande, car par défaut, "(.*)"elle correspondra à tout "file path/level1/level2" xxx some="xxx".

Au lieu de cela, vous pouvez rendre votre point-star non gourmand, ce qui le fera correspondre le moins de caractères possible:

/location="(.*?)"/

L'ajout d'un ?sur un quantificateur ( ?, *ou +) le rend non gourmand.

Daniel Vandersluis
la source
32
FWIW, dans le cas où vous utilisez VIM, cette expression régulière doit être un peu différente: au lieu d' .*?être .\{-}pour une correspondance non gourmande.
SooDesuNe
44
Merci Daniel. "L'ajout d'un? Sur un quantificateur (?, * Ou +) le rend non gourmand." est un conseil utile pour moi.
PhatHV
10
Le ? décrit ma confusion en essayant de comprendre cela. Comme c'est approprié.
Robbie Smith
1
Je crois que vous pouvez dire «paresseux» au lieu de «non gourmand»
Manticore
50

location="(.*)"correspondra de l '"après location=au" après, some="xxxsauf si vous le rendez non gourmand. Donc, vous devez soit .*?(c'est-à-dire le rendre non gourmand) ou mieux remplacer .*par [^"]*.

sepp2k
la source
3
[^ "] * est aussi probablement plus rapide avec la plupart des moteurs d'expression régulière car il n'a pas besoin de rechercher le modèle après le modèle actuel.
Jean Vincent
1
@Kip: Vous avez probablement raison, mais la .*?notation est plus générale que[^"]*
Bondax
que diriez-vous si je veux inclure le caractère délimiteur en utilisant [^ "] *
Frohlich
pas du tout, si vous ne savez pas ce que ^ et [] signifient ici. La plupart des gens comprendront. *
Vincent Gerris
31

Que diriez-vous

.*location="([^"]*)".*

Cela évite la recherche illimitée avec. * Et correspond exactement à la première citation.

utilisateur193690
la source
En raison de divergences dans grep, ce qui précède devrait être le modèle préféré si la portabilité est un problème.
Josh Habdas
22

Utilisez une correspondance non gourmande, si votre moteur le prend en charge. Ajouter le ? à l'intérieur de la capture.

/location="(.*?)"/
codenheim
la source
11

L'utilisation de quantificateurs paresseux ?sans indicateur global est la réponse.

Par exemple,

entrez la description de l'image ici

Si vous aviez alors le drapeau global /g, il aurait correspondu à toutes les correspondances de longueur la plus faible comme ci-dessous. entrez la description de l'image ici

Uddhav Gautam
la source
1

Parce que vous utilisez un sous- motif quantifié et comme décrit dans Perl Doc ,

Par défaut, un sous-motif quantifié est " gourmand ", c'est-à-dire qu'il correspondra autant de fois que possible (étant donné un emplacement de départ particulier) tout en permettant au reste du motif de correspondre. Si vous voulez qu'il corresponde au nombre minimum de fois possible, suivez le quantificateur avec un "?" . Notez que les significations ne changent pas, juste la "gourmandise":

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

Ainsi, pour permettre à votre modèle quantifié de faire une correspondance minimale, suivez-le en ?:

/location="(.*?)"/
Mohammad Kanan
la source
1

Voici une autre façon.

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

Le premier élément: [\s\S]*?(?:location="[^"]*")[\s\S]* remplacer par:$1

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


Pour être complet, ceci obtient le dernier. C'est gourmand[\s\S]*

Le dernier élément:[\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 ?

Stephen Sherry
la source