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.


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.


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 [^"]*.


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.


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="(.*?)"/

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


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="(.*?)"/

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 ?

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.