790 votes

Comment faire correspondre "tout ce qui va jusqu'à cette séquence de caractères" dans une expression régulière ?

Prenez cette expression régulière : /^[^abc]/ . Cela correspondra à tout caractère unique au début d'une chaîne, à l'exception de a, b ou c.

Si vous ajoutez un * après elle - /^[^abc]*/ - l'expression régulière continuera à ajouter chaque caractère suivant au résultat, jusqu'à ce qu'elle rencontre soit un a , ou b , ou c .

Par exemple, avec la chaîne source "qwerty qwerty whatever abc hello" l'expression correspondra à "qwerty qwerty wh" .

Mais si je voulais que la chaîne correspondante soit "qwerty qwerty whatever "

...En d'autres termes, comment puis-je faire correspondre tout jusqu'à (mais pas y compris) la séquence exacte "abc" ?

0 votes

Que voulez-vous dire par match but not including ?

9 votes

Je veux dire que je veux correspondre "qwerty qwerty whatever " - sans compter les "abc". En d'autres termes, je Ne le fais pas. voulez que la correspondance résultante soit "qwerty qwerty whatever abc" .

4 votes

En javascript, vous pouvez simplement do string.split('abc')[0] . Ce n'est certainement pas une réponse officielle à ce problème, mais je trouve que c'est plus simple que les regex.

1403voto

sidyll Points 20176

Vous n'avez pas spécifié quelle sorte de regex vous utilisez, mais cela fonctionnera dans n'importe laquelle des plus populaires qui peuvent être considérées comme "complètes".

/.+?(?=abc)/

Comment cela fonctionne

Le site .+? est la version non gourmande de .+ (un ou plusieurs de n'importe quoi). Lorsque nous utilisons .+ le moteur va essentiellement tout faire correspondre. Ensuite, s'il y a quelque chose d'autre dans la regex, il reviendra en arrière par étapes en essayant de faire correspondre la partie suivante. C'est le gourmand comportement, signification dans la mesure du possible, pour satisfaire .

Lorsque vous utilisez .+? Au lieu de faire correspondre tous les caractères d'un coup et de revenir en arrière pour d'autres conditions (le cas échéant), le moteur fera correspondre les caractères suivants par jusqu'à ce que la partie suivante de la regex soit trouvée (encore une fois, s'il y en a). C'est le non avare , ce qui veut dire que la correspondance le moins possible pour satisfaire .

/.+X/  ~ "abcXabcXabcX"        /.+/  ~ "abcXabcXabcX"
          ^^^^^^^^^^^^                  ^^^^^^^^^^^^

/.+?X/ ~ "abcXabcXabcX"        /.+?/ ~ "abcXabcXabcX"
          ^^^^                          ^

En suivant cela, nous avons (?={contents}) , a largeur zéro assertion , a regardez autour de vous . Cette construction groupée correspond à son mais ne compte pas les caractères correspondants ( largeur zéro ). Il s'agit de renvoie seulement s'il s'agit d'une correspondance ou non ( assertion ).

Ainsi, en d'autres termes, la regex /.+?(?=abc)/ signifie :

Faites correspondre le moins de caractères possible jusqu'à ce qu'un "abc" soit trouvé, sans compter les "abc".

30 votes

Cela ne fonctionnera probablement pas avec les sauts de ligne, s'ils sont censés être capturés.

4 votes

Quelle est la différence entre .+? y .* ?

9 votes

@robbie0630 + signifie 1 ou plus, où * signifie 0 ou plus. L'inclusion/exclusion de la ? le rendra avide ou non avide.

195voto

Jared Ng Points 2013

Si vous cherchez à capturer tout jusqu'à "abc" :

/^(.*?)abc/

Explication :

( ) capturer l'expression à l'intérieur des parenthèses pour l'accès en utilisant $1 , $2 etc.

^ correspond au début de la ligne

.* correspondre à quoi que ce soit, ? non gracieux (correspond au nombre minimum de caractères requis) - [1].

1] La raison pour laquelle cela est nécessaire est qu'autrement, dans la chaîne suivante :

whatever whatever something abc something abc

par défaut, les regex sont gourmand ce qui signifie qu'il correspondra autant que possible. Par conséquent, /^.*abc/ correspondrait à "whatever whatever something abc something ". Ajout du quantificateur non gourmand ? fait en sorte que la regex ne corresponde qu'à "whatever whatever something ".

9 votes

Merci, mais le vôtre fait inclure l'abc dans le match. En d'autres termes, la correspondance résultante est "whatever whatever something abc".

1 votes

Pourriez-vous expliquer ce que vous essayez de faire ? Si votre scénario est : (A) Vous voulez obtenir tout ce qui va jusqu'à "abc" -- utilisez simplement des parenthèses autour de ce que vous voulez capturer. (B) Vous voulez faire correspondre la chaîne de caractères jusqu'à "abc" -- vous devez vérifier l'abc de toute façon, donc il doit faire partie de la regex de toute façon. Comment vérifier autrement qu'il est là ?

1 votes

sed ne semble pas supporter la correspondance non avide, ni le look-around ( (?=...) ). Que puis-je faire d'autre ? Exemple de commande : echo "ONE: two,three, FOUR FIVE, six,seven" | sed -n -r "s/^ONE: (.+?), .*/\1/p" renvoie à two,three, FOUR FIVE mais je m'attends à ce que two,three ...

89voto

Devy Points 588

Comme @Jared Ng et @Issun l'ont souligné, la clé pour résoudre ce type de RegEx comme "tout faire correspondre jusqu'à un certain mot ou une certaine sous-chaîne" ou "tout faire correspondre après un certain mot ou une certaine sous-chaîne" est appelée assertions de longueur zéro "lookaround". Pour en savoir plus, cliquez ici.

Dans votre cas particulier, il peut être résolu par un regard positif sur l'avenir : .+?(?=abc)

Une image vaut mille mots. Voir l'explication détaillée dans la capture d'écran.

Regex101 Screenshot

51 votes

.+?(?=abc) La regex copier-passer vaut plus.

1 votes

Qu'en est-il de l'exclusion des espaces de tête ?

1 votes

Un lien partageable vaut aussi plus qu'une capture d'écran, je plaisante, merci pour la réponse.

9voto

Issun Points 7271

Ce dont vous avez besoin est de regarder autour de l'affirmation comme .+? (?=abc) .

Voir : Assertions de longueur zéro Lookahead et Lookbehind

Sachez que [abc] n'est pas la même chose que abc . À l'intérieur des crochets, ce n'est pas une chaîne de caractères - chaque caractère n'est qu'une possibilité parmi d'autres. En dehors des parenthèses, cela devient la chaîne de caractères.

8voto

707 Points 366

Pour les regex en Java, et je crois aussi dans la plupart des moteurs de regex, si vous voulez inclure la dernière partie, cela fonctionnera :

.+?(abc)

Par exemple, dans cette ligne :

I have this very nice senabctence

sélectionner tous les caractères jusqu'à "abc" et inclure également abc

en utilisant notre regex, le résultat sera : I have this very nice senabc

Testez-le : https://regex101.com/r/mX51ru/1

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