Prenez cette expression régulière: /^[^abc]/
. Cela correspondra à n'importe quel caractère au début d'une chaîne, à l'exception de a, b ou c.
Si vous ajoutez un *
après - /^[^abc]*/
- l'expression régulière continuera à ajouter chaque caractère suivant le résultat, jusqu'à ce qu'il 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 (sans inclure) la séquence exacte "abc"
?
match but not including
?"qwerty qwerty whatever "
- sans inclure le "abc". En d'autres termes, je ne veux pas que la correspondance résultante soit"qwerty qwerty whatever abc"
.do string.split('abc')[0]
. Certainement pas une réponse officielle à ce problème, mais je le trouve plus simple que regex.Réponses:
Vous n'avez pas spécifié quelle saveur de regex vous utilisez, mais cela fonctionnera dans l'un des plus populaires qui peuvent être considérés comme "complets".
Comment ça fonctionne
La
.+?
partie est la version non gourmande de.+
(un ou plusieurs de n'importe quoi). Lorsque nous utilisons.+
, le moteur correspondra à tout. Ensuite, s'il y a autre chose dans l'expression régulière, elle reviendra par étapes en essayant de faire correspondre la partie suivante. C'est le comportement gourmand , c'est- à- dire autant que possible à satisfaire .Lors de l'utilisation
.+?
, au lieu de faire correspondre tout à la fois et de revenir à d'autres conditions (le cas échéant), le moteur fera correspondre les caractères suivants par étape jusqu'à ce que la partie suivante de l'expression régulière soit mise en correspondance (à nouveau le cas échéant). C'est le non gourmand , c'est -à- dire le match le moins possible à satisfaire .Après cela, nous avons , une assertion de largeur nulle , un regard autour . Cette construction groupée correspond à son contenu, mais ne compte pas comme des caractères correspondants ( largeur nulle ). Il ne retourne que s'il s'agit d'une correspondance ou non ( assertion ).
(?=
{contents}
)
Ainsi, en d'autres termes, l'expression régulière
/.+?(?=abc)/
signifie:la source
.+?
et.*
?+
signifie 1 ou plus, où*
0 ou plus. L'inclusion / exclusion de la?
rendra gourmande ou non gourmande.^(?:(?!abc)(?!def).)*
vous pouvez chaîner pour exclure les motifs que vous ne voulez pas et il récupérera tout comme nécessaire, même si le motif n'existe pasSi vous cherchez à tout capturer jusqu'à "abc":
Explication:
( )
capturer l'expression à l' intérieur des parenthèses pour l' accès à l' aide$1
,$2
etc.^
correspondre au début de la ligne.*
correspondre à n'importe quoi,?
sans gourmandise (correspondre 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:
par défaut, les regex sont gourmandes , ce qui signifie qu'elles correspondront autant que possible. Par conséquent
/^.*abc/
, correspondrait à "quoi que ce soit quelque chose abc quelque chose". L'ajout du quantificateur non gourmand?
fait que l'expression régulière ne correspond qu'à «quoi que ce soit».la source
sed
ne semble pas prendre en charge la correspondance non gourmande, ni la recherche autour ((?=...)
). Que puis-je faire d'autre? Exemple de commande:echo "ONE: two,three, FOUR FIVE, six,seven" | sed -n -r "s/^ONE: (.+?), .*/\1/p"
retournetwo,three, FOUR FIVE
, mais j'attendstwo,three
...two
pas, pastwo,three
.Comme l'ont souligné @Jared Ng et @Issun, la clé pour résoudre ce type de RegEx comme "tout faire correspondre jusqu'à un certain mot ou une sous-chaîne" ou "tout faire correspondre après un certain mot ou une certaine sous-chaîne" est appelée assertions de longueur nulle "lookaround" . En savoir plus à leur sujet ici.
Dans votre cas particulier, cela peut être résolu par un regard positif sur l'avenir:
.+?(?=abc)
Une image vaut mieux que mille mots. Voir l'explication détaillée dans la capture d'écran.
la source
.+?(?=abc)
regex copier-coller vaut plus.Ce dont vous avez besoin, c'est de regarder autour de l'assertion comme
.+? (?=abc)
.Voir: Lookahead et Lookbehind Zero-Length Assertions
Sachez que ce
[abc]
n'est pas la même chose queabc
. Entre crochets, 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.la source
Pour regex en Java, et je crois aussi dans la plupart des moteurs regex, si vous voulez inclure la dernière partie, cela fonctionnera:
Par exemple, dans cette ligne:
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 cela: https://regex101.com/r/mX51ru/1
la source
Je me suis retrouvé dans cette question de stackoverflow 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 l'expression régulière dont j'avais besoin:
Comme vous pouvez le voir, j'avais besoin d'un dossier avant le dossier "grp-bps", sans inclure le dernier tiret. Et il fallait avoir au moins un dossier après le dossier "grp-bps".
Éditer
Version texte pour copier-coller (changez 'grp-bps' pour votre texte):
la source
Cela aura un sens sur l'expression régulière.
Ici, nous pouvons obtenir le mot exact globalement qui appartient à l'intérieur des guillemets doubles. Par exemple, si notre texte de recherche est,
Voici l'exemple des mots "entre guillemets"
nous obtiendrons alors "double guillemet" de cette phrase.
la source
"
ce qui, à mes yeux, ne semble pas pertinent pour la question.Sur python:
.+?(?=abc)
fonctionne pour le cas d'une seule ligne.[^]+?(?=abc)
ne fonctionne pas, car python ne reconnaît pas [^] comme expression régulière valide. Pour que la correspondance multiligne fonctionne, vous devrez utiliser l'option re.DOTALL, par exemple:la source
Je pense 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:
Faire quelque chose comme
^[^(abc)]
ça devrait faire l'affaire.la source
Le
$
marque la fin d'une chaîne, donc quelque chose comme ça devrait fonctionner:[[^abc]*]$
où vous cherchez quelque chose qui ne se termine PAS dans une itération deabc
, mais cela devrait être à la finDe plus, si vous utilisez un langage de script avec regex (comme php ou js), ils ont une fonction de recherche qui s'arrête quand il rencontre pour la première fois un modèle (et vous pouvez spécifier commencer par la gauche ou commencer par la droite, ou avec php, vous pouvez faire un implosage pour refléter la chaîne).
la source
essaye ça
Requete :
production :
la source