web-dev-qa-db-fra.com

Comment faire correspondre "n'importe quoi jusqu'à cette séquence de caractères" dans une expression régulière?

Prenez cette expression régulière: /^[^abc]/. Cela correspond à n'importe quel caractère au début d'une chaîne, sauf a, b ou c.

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

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

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

... En d'autres termes, comment puis-je associer tout jusqu'à la séquence exacte"abc" (sans l'inclure)?

373
callum

Vous n’avez pas précisé le type de regex que vous utilisez, mais cela fonctionnera dans l’un des plus populaires qui peuvent être considérés comme "complets".

/.+?(?=abc)/

Comment ça marche

La partie .+? est la version peu gourmande de .+ (un ou plusieurs de Rien). Lorsque nous utilisons .+, le moteur correspondra à tout… .. Ensuite, s'il y a quelque chose d'autre dans la regex, il retournera par étapes En essayant de faire correspondre la partie suivante. C’est le comportement gourmand _ _ _ _ _ _ _ autant que possible pour satisfaire} __.

Lorsqu’on utilise .+?, au lieu de tout faire en une fois et de revenir à D’autres conditions (le cas échéant), le moteur fera correspondre les caractères suivants de Step jusqu'à ce que la partie suivante de l’expression rationnelle corresponde (à nouveau le cas échéant) . Ceci est le non avide, signifiant match le moins possible à Satisfaire.

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

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

Après cela, nous avons (?={contents}), une largeur nulle Assertion, un regarder autour de. Cette construction groupée correspond à son contenu , Mais ne compte pas comme caractères correspondants (largeur zéro). Il ne renvoie que s'il s'agit d'une correspondance ou non (assertion).

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

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

732
sidyll

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

/^(.*?)abc/

Explication:

( ) capturer l'expression entre les parenthèses pour l'accès à l'aide de $1, $2, etc.

^ correspond au début de la ligne

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

[1] La raison pour laquelle cela est nécessaire est que sinon, dans la chaîne suivante:

whatever whatever something abc something abc

par défaut, les expressions rationnelles sont greedy , ce qui signifie que cela correspond le plus possible. Donc, /^.*abc/ correspondrait à "quoi que ce soit quelque chose abc quelque chose". L'ajout du quantificateur non-glouton ? fait en sorte que l'expression régulière ne corresponde que "peu importe le contenu".

89
Jared Ng

Comme @Jared Ng et @Issun l'ont fait remarquer, la clé pour résoudre ce type de RegEx est de "faire correspondre tout à un certain mot ou une certaine chaîne" ou "faire correspondre tout après un certain mot ou une certaine chaîne" s'appelle "assertions" de longueur nulle . En savoir plus sur eux ici.

Dans votre cas particulier, cela peut être résolu par un regard positif. Une image vaut mieux que mille mots. Voir l'explication détaillée dans la capture d'écran.

 Regex101 Screenshot

32
Devy

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

Voir: Lookahead et Lookbehind Zero-Length Assertions

Sachez que [abc] est différent de abc. Entre parenthèses, ce n’est pas une chaîne - chaque caractère n’est qu’une des possibilités. En dehors des crochets, il devient la chaîne.

8
aevanko

Cela fera sens à propos de regex.

  1. Le mot exact peut être obtenu à partir de la commande regex suivante:

("(.*?)")/g

Ici, nous pouvons obtenir globalement le mot exact qui appartient aux guillemets doubles . Par exemple, Si notre texte de recherche est, 

Ceci est l'exemple pour les mots "double citation"

alors nous aurons "double cité" de cette phrase.

3

Pour 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 ceci: https://regex101.com/r/mX51ru/1

2
707

J'ai fini par poser cette question après avoir cherché de l'aide pour résoudre mon problème, mais je n'ai trouvé aucune solution :(

J'ai donc dû improviser ... après un certain temps, j'ai réussi à atteindre la regex dont j'avais besoin:

 enter image description here

Comme vous pouvez le constater, il me fallait jusqu'à un dossier en avance du dossier "grp-bps", sans inclure le dernier tiret. Et il était nécessaire d'avoir au moins un dossier après le dossier "grp-bps".

0
Loaderon

Je crois que vous avez besoin de sous-expressions. Si je me souviens bien, vous pouvez utiliser les crochets normaux () pour les sous-expressions.

Cette partie est du manuel de grep:

 Back References and Subexpressions
       The back-reference \n, where n is a single digit, matches the substring
       previously matched  by  the  nth  parenthesized  subexpression  of  the
       regular expression.

Faites quelque chose comme ^[^(abc)] devrait faire l'affaire.

0
Software Mechanic