Question Expressions régulières et négation d'un groupe de caractères entier [dupliquer]


Cette question a déjà une réponse ici:

Je tente quelque chose qui, selon moi, devrait être assez évident pour moi, mais ce n'est pas le cas. J'essaie de faire correspondre une chaîne qui ne contient PAS une séquence de caractères spécifique. J'ai essayé d'utiliser [^ab], [^(ab)], etc. pour faire correspondre les chaînes ne contenant pas de 'a' ou de 'b', ou seulement de 'a' ou seulement de 'b' ou de 'ba' mais ne pas correspondre sur 'ab'. Les exemples que j'ai donnés ne correspondront pas à «ab», mais ils ne correspondront pas à un seul et j'en ai besoin. Y a-t-il un moyen simple de le faire?


151
2018-06-10 18:04


origine


Réponses:


Utilisez le lookahead négatif:

^(?!.*ab).*$

MISE À JOUR: Dans les commentaires ci-dessous, j'ai déclaré que cette approche est plus lente que celle donnée dans La réponse de Peter. J'ai fait quelques tests depuis et j'ai trouvé que c'était légèrement plus rapide. Cependant, la raison de préférer cette technique à l'autre n'est pas la rapidité, mais la simplicité.

L'autre technique, décrite ici comme un jeton gourmand trempé, est adapté à des problèmes plus complexes, comme la correspondance de texte délimité où les délimiteurs se composent de plusieurs caractères (comme HTML, comme Luke l'a commenté) au dessous de). Pour le problème décrit dans la question, c'est exagéré.

Pour tous ceux qui sont intéressés, j'ai testé avec une grande partie du texte Lorem Ipsum, en comptant le nombre de lignes qui ne contiennent pas le mot "quo". Ce sont les regexes que j'ai utilisées:

(?m)^(?!.*\bquo\b).+$

(?m)^(?:(?!\bquo\b).)+$

Que je recherche des correspondances dans tout le texte ou que je les divise en lignes et les associe individuellement, le style de base ancré surpasse systématiquement celui qui est flottant.


148
2018-06-10 18:10



Utiliser une classe de caractères telle que [^ab] correspondra à un un seul caractère ce n'est pas dans l'ensemble des caractères. (Avec le ^ être la partie négative).

Pour faire correspondre une chaîne qui ne contient pas la séquence multi-caractères ab, vous voulez utiliser un lookahead négatif:

^(?:(?!ab).)+$


Et l'expression ci-dessus désélectionnée en mode commentaire regex est:

(?x)    # enable regex comment mode
^       # match start of line/string
(?:     # begin non-capturing group
  (?!   # begin negative lookahead
    ab  # literal text sequence ab
  )     # end negative lookahead
  .     # any single character
)       # end non-capturing group
+       # repeat previous match one or more times
$       # match end of line/string

284
2018-06-10 18:11



Oui on l'appelle négatif lookahead. Ça va comme ça - (?!regex here). Alors abc(?!def) va correspondre à abc ne pas suivi par def. Donc, il va correspondre à abce, abc, abck, etc.

De même, il y a une recherche positive - (?=regex here). Alors abc(?=def) va correspondre à abc suivi de def.

Il y a aussi un lookbehind négatif et positif - (?<!regex here) et (?<=regex here) respectivement

Un point à noter est que le résultat négatif est nul. Autrement dit, cela ne compte pas comme ayant pris de la place.

Donc ça peut ressembler a(?=b)c correspondra à "abc" mais ce ne sera pas le cas. Il correspondra à "a", puis au test positif avec "b" mais il ne sera pas avancé dans la chaîne. Ensuite, il essaiera de faire correspondre le "c" avec "b", ce qui ne fonctionnera pas. De même ^a(?=b)b$ correspondra à "ab" et non à "abb" car les vues sont de largeur nulle (dans la plupart des implémentations de regex).

Plus d'informations sur ce page


43
2018-06-10 18:16



Utiliser une regex comme vous l'avez décrit est la méthode simple (pour autant que je sache). Si vous voulez une plage, vous pouvez utiliser [^ a-f].


6
2018-06-10 18:10



Le moyen le plus simple est de tirer entièrement la négation de l'expression régulière:

if (!userName.matches("^([Ss]ys)?admin$")) { ... }

5
2018-06-10 18:16



abc (?! def) correspondra à abc non suivi   par def. Donc ça va correspondre à abce, abc,   abck, etc. et si je ne veux ni déf   ni xyz sera-t-il abc (?! (def) (xyz))   ???

J'ai eu la même question et trouvé une solution:

abc(?:(?!def))(?:(?!xyz))

Ces groupes sans comptage sont combinés par "ET", donc cela devrait faire l'affaire. J'espère que cela aide.


4
2017-11-17 13:10



L'expression rationnelle [^ (ab)] correspondra par exemple à 'ab ab ab ab' mais pas à 'ab', car elle correspondra à la chaîne 'a' ou 'b'.

Quelle langue / scénario avez-vous? Pouvez-vous soustraire les résultats de l'ensemble d'origine et ne faire que correspondre à ab?

Si vous utilisez GNU grep et que vous analysez des entrées, utilisez l'indicateur '-v' pour inverser vos résultats, en renvoyant tous les non-matches. D'autres outils de regex ont également une fonction 'return nonmatch'.

Si je comprends bien, vous voulez tout sauf pour les éléments qui contiennent «ab» n'importe où.


3
2018-06-10 18:13