Correspond à tout sauf pour les chaînes spécifiées

119

Je sais que l'expression régulière suivante correspondra à «rouge», «vert» ou «bleu».

red|green|blue

Existe-t-il un moyen simple de faire correspondre tout sauf plusieurs chaînes spécifiées?

Alfred
la source
1
Tous les types d'expressions régulières ne peuvent pas faire cela. Dans quel environnement travaillez-vous? Java? Perl? .NET? Une bibliothèque de regex C / C ++? Un SGBDR?
FrustratedWithFormsDesigner
8
Vous ne dites pas ce que vous voulez, mais vous pouvez simplement inverser le sens de l'opération "match". Cela ne vous aidera pas si vous essayez de faire une extraction sur les parties non correspondantes, mais pour tester si une chaîne exclue n'est pas présente, cela fonctionnerait: if (!s.match(/red|green|blue/)) ... Remarque: je sais que l'OP ne spécifie pas la langue / le cadre, donc ce qui précède doit être considéré comme un exemple générique et non normatif.
tvanfosson

Réponses:

154

Si vous voulez vous assurer que la chaîne n'est ni rouge, ni verte, ni bleue, la réponse de caskey est la suivante. Ce que l'on souhaite souvent, cependant, c'est de s'assurer que la ligne ne contient nulle part de rouge, de vert ou de bleu. Pour cela, ancrez l'expression régulière avec ^et incluez .*dans l'anticipation négative:

^(?!.*(red|green|blue))

Supposons également que vous vouliez des lignes contenant le mot "moteur" mais sans aucune de ces couleurs:

^(?!.*(red|green|blue)).*engine

Vous pourriez penser que vous pouvez factoriser le .*en tête de l'expression régulière:

^.*(?!red|green|blue)engine     # Does not work

mais tu ne peux pas. Vous devez avoir les deux instances de .*pour que cela fonctionne.

Wayne Conrad
la source
48

Cela dépend de la langue, mais il y a généralement des affirmations négatives que vous pouvez insérer comme suit:

(?!red|green|blue)

(Merci pour le correctif de syntaxe, ce qui précède est Java et Perl valides, YMMV)

caskey
la source
2
@caskey, La réponse complète est une combinaison du mien et du vôtre. Si vous souhaitez les fusionner, je supprimerai le mien.
Wayne Conrad
14
Cette réponse serait beaucoup plus utile si vous l'avez un peu expliquée. Par exemple: Que signifie "?" et "!" signifier? Pourquoi avez-vous besoin de groupes de capture?
Lii
C'est aussi du Python valide.
Joe Mornin
vient de l'utiliser avec la bibliothèque Delphi regEx et cela ne fonctionne que comme ceci: ^ (?! rouge | vert | bleu). C'est également vrai pour le tester sur regex101.com . Est-ce que ce qui précède est une faute de frappe qui manque un ^ ou est-ce que ça fonctionne réellement comme ça en Java / Perl / Python ..?
Peter
33

Faire correspondre tout sauf des chaînes données

Si vous voulez faire correspondre la chaîne entière où vous voulez faire correspondre tout sauf certaines chaînes, vous pouvez le faire comme ceci:

^(?!(red|green|blue)$).*$

Cela dit, commencez la correspondance depuis le début de la chaîne où elle ne peut pas commencer et se terminer par du rouge, du vert ou du bleu et faire correspondre tout le reste jusqu'à la fin de la chaîne.

Vous pouvez l'essayer ici: https://regex101.com/r/rMbYHz/2

Notez que cela ne fonctionne qu'avec les moteurs regex qui prennent en charge une anticipation négative .

Sam
la source
23

Vous n'avez pas besoin d'une anticipation négative. Il y a un exemple de travail:

/([\s\S]*?)(red|green|blue|)/g

La description:

  • [\s\S] - correspond à n'importe quel caractère
  • * - match de 0 à illimité du groupe précédent
  • ? - correspond le moins possible
  • (red|green|blue|) - correspond à l'un de ces mots ou rien
  • g - motif répété

Exemple:

whiteredwhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredwhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredredgreenredgreenredgreenredgreenredgreenbluewhiteredbluewhiteredbluewhiteredbluewhiteredbluewhiteredwhite

Sera:

whitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhite

Essaye-le: regex101.com

hlcs
la source
4
Vous pouvez réduire considérablement le nombre de pas en échangeant [\ s \ S] pour un point. J'étais très confus pourquoi apparemment tous les autres exemples capturent chaque mot individuellement. Cette façon est légèrement plus d'étapes regex mais nécessite beaucoup moins de post-traitement.
Zatronium
3
mais cela ne fait pas de correspondance (validation de texte), cela supprime simplement le texte spécifié lors de la substitution.
Marek R
Cette solution ne sortira pas le dernier morceau de texte après les mots connus. Donc, il n'est pas nécessaire de comparer la vitesse, c'est tout simplement faux.
Wiktor Stribiżew
@ WiktorStribiżew corrigé.
hlcs
10

J'avais la même question, les solutions proposées fonctionnaient presque mais elles avaient quelques problèmes. À la fin, l'expression régulière que j'ai utilisée est:

^(?!red|green|blue).*

Je l'ai testé en Javascript et .NET.

. * ne devrait pas être placé à l'intérieur de l'anticipation négative comme ceci: ^ (?!. * rouge | vert | bleu) ou cela rendrait le premier élément différent du reste (c'est-à-dire que "anotherred" ne correspondrait pas tant que " un autre vert "serait)

Durden81
la source
3

Faire correspondre n'importe quel texte mais ceux qui correspondent à un modèle est généralement obtenu en divisant la chaîne avec le modèle regex .

Exemples :

  • - Regex.Split(text, @"red|green|blue")ou, pour se débarrasser des valeurs vides, Regex.Split(text, @"red|green|blue").Where(x => !string.IsNullOrEmpty(x))(voir démo )
  • - Regex.Split(text, "red|green|blue")ou, pour supprimer les éléments vides, Regex.Split(text, "red|green|blue").Where(Function(s) Not String.IsNullOrWhitespace(s))(voir la démo , ou cette démo où LINQ est pris en charge)
  • - text.split(/red|green|blue/)(pas besoin d'utiliser le gmodificateur ici!) (pour se débarrasser des valeurs vides, utilisez text.split(/red|green|blue/).filter(Boolean)), voir démo
  • - text.split("red|green|blue"), ou - pour conserver tous les éléments vides de fin - utilisez text.split("red|green|blue", -1), ou pour supprimer tous les éléments vides, utilisez plus de code pour les supprimer (voir démo )
  • - Similaire à Java text.split(/red|green|blue/),, pour utiliser tous les éléments de fin text.split(/red|green|blue/, -1)et pour supprimer tous les éléments vides text.split(/red|green|blue/).findAll {it != ""})(voir démo )
  • - text.split(Regex("red|green|blue"))ou, pour supprimer les éléments vides, utilisez text.split(Regex("red|green|blue")).filter{ !it.isBlank() }, voir la démo
  • - text.split("red|green|blue"), ou pour conserver tous les éléments vides de fin, utilisez text.split("red|green|blue", -1)et pour supprimer tous les éléments vides, utilisez text.split("red|green|blue").filter(_.nonEmpty)(voir démo )
  • - text.split(/red|green|blue/), pour se débarrasser des valeurs vides, utilisez .split(/red|green|blue/).reject(&:empty?)(et pour obtenir les éléments vides de début et de fin, utilisez -1comme deuxième argument, .split(/red|green|blue/, -1)) (voir démo )
  • - my @result1 = split /red|green|blue/, $text;, ou avec tous les éléments vides de fin my @result2 = split /red|green|blue/, $text, -1;, ou sans aucun élément vide, my @result3 = grep { /\S/ } split /red|green|blue/, $text;(voir démo )
  • - preg_split('~red|green|blue~', $text)ou preg_split('~red|green|blue~', $text, -1, PREG_SPLIT_NO_EMPTY)pour afficher aucun élément vide (voir démo )
  • - re.split(r'red|green|blue', text)ou, pour supprimer les éléments vides, list(filter(None, re.split(r'red|green|blue', text)))(voir démo )
  • - Utilisez regexp.MustCompile("red|green|blue").Split(text, -1), et si vous devez supprimer des éléments vides, utilisez ce code . Voir la démo de Go .

REMARQUE : Si vos modèles contiennent des groupes de capture , les fonctions / méthodes de fractionnement regex peuvent se comporter différemment, en fonction également d'options supplémentaires. Veuillez vous référer à la documentation appropriée de la méthode de fractionnement.

Wiktor Stribiżew
la source
0

Tous sauf le mot "rouge"

var href = '(text-1) (red) (text-3) (text-4) (text-5)';

var test = href.replace(/\((\b(?!red\b)[\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Tous sauf le mot "rouge"

var href = '(text-1) (frede) (text-3) (text-4) (text-5)';

var test = href.replace(/\(([\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = p1.replace(/red/g, '');
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Юрий Светлов
la source