web-dev-qa-db-fra.com

RegEx - Exclure les modèles correspondants

J'ai les modèles ci-dessous à exclure.

make it cheaper
make it cheapere
makeitcheaper.com.au
makeitcheaper
making it cheaper
www.make it cheaper
ww.make it cheaper.com

J'ai créé une expression régulière pour correspondre à l'un d'eux. Cependant, je veux obtenir tout le reste autre que ceux-ci. Je ne sais pas comment inverser cette expression régulière que j'ai créée.

mak(e|ing) ?it ?cheaper

Le modèle ci-dessus correspond à toutes les chaînes répertoriées. Maintenant, je veux qu'il corresponde à tout le reste. Comment fait-on ça?

De la recherche, il semble que j'ai besoin de quelque chose comme lookahead/look back négatif. Mais je ne comprends pas vraiment. Quelqu'un peut me diriger dans la bonne direction?

15
San

Vous pouvez simplement le mettre dans une perspective négative comme ceci:

(?!mak(e|ing) ?it ?cheaper)

Tout comme ça ne fonctionnera pas puisque, si vous faites un matches1, il ne correspondra pas puisque vous regardez juste vers l'avant, vous ne correspondez en fait à rien et, si vous faites un find1, il correspondra plusieurs fois, car vous pouvez commencer à partir de nombreux endroits de la chaîne où les caractères suivants ne correspondent pas à ce qui précède.

Pour résoudre ce problème, selon ce que vous souhaitez faire, nous avons 2 choix:

  1. Si vous souhaitez exclure toutes les chaînes qui sont exactement l'une de celles-ci (c'est-à-dire "rendre moins cherblahblah" n'est pas exclue), vérifiez pour début (^) Et fin ($) de chaîne:

    ^(?!mak(e|ing) ?it ?cheaper$).*
    

    Le .* (Zéro ou plusieurs caractères génériques) est la correspondance réelle qui a lieu. Les contrôles d'anticipation négatifs du premier caractère.

  2. Si vous souhaitez exclure toutes les chaînes contenant l'une d'entre elles, vous pouvez vous assurer que l'anticipation ne correspond pas avant chaque caractère que nous correspondons:

    ^((?!mak(e|ing) ?it ?cheaper).)*$
    

    Une alternative est d'ajouter des caractères génériques au début de votre anticipation (c'est-à-dire d'exclure toutes les chaînes qui, depuis le début de la chaîne, contiennent n'importe quoi, puis votre modèle), mais je ne vois actuellement aucun avantage à cela ( une longueur d'anticipation arbitraire est également moins susceptible d'être prise en charge par un outil donné):

    ^(?!.*mak(e|ing) ?it ?cheaper).*
    

En raison de ^ Et $, Faire soit un find soit un matches fonctionnera pour l'un des deux ci-dessus (cependant, dans le cas de matches, le ^ est facultatif et, dans le cas de find, le .* en dehors de l'anticipation est facultatif).


1: Bien qu'ils ne puissent pas être appelés ainsi, de nombreuses langues ont des fonctions équivalentes à matches et find avec regex.


Ce qui précède est la réponse strictement rationnelle à cette question.

Une meilleure approche pourrait être de s'en tenir à l'expression rationnelle d'origine (mak(e|ing) ?it ?cheaper) et de voir si vous pouvez annuler les correspondances directement avec l'outil ou la langue que vous utilisez.

En Java, par exemple, cela impliquerait de faire if (!string.matches(originalRegex)) (notez le !, Qui annule le booléen renvoyé) au lieu de if (string.matches(negLookRegex)).

23
Dukeling

Le lookahead négatif, je crois, c'est ce que vous recherchez. Essayez peut-être:

(?!.*mak(e|ing) ?it ?cheaper)

Et peut-être un peu plus flexible:

(?!.*mak(e|ing) *it *cheaper)

Juste au cas où il y aurait plus d'un espace.

7
Jerry