web-dev-qa-db-fra.com

Regex pour faire correspondre tous les mots sauf une liste donnée

J'essaie d'écrire une expression régulière de remplacement pour entourer tous les mots de guillemets, à l'exception des mots AND, OR et NOT. 

J'ai essayé ce qui suit pour la partie match de l'expression:

(?i)(?<Word>[a-z0-9]+)(?<!and|not|or)

et 

(?i)(?<Word>[a-z0-9]+)(?!and|not|or)

mais ni travail. L'expression de remplacement est simple et entoure actuellement tous les mots.

"${Word}"

Alors 

Ceci et cela pas cela

devient 

"Ceci" et "ceci" pas "cela"

18
John

C'est un peu sale, mais ça marche:

(?<!\b(?:and| or|not))\b(?!(?:and|or|not)\b)

En clair, cela correspond à toute limite de mot non précédée et non suivie de "et", "ou", ou "pas". Il correspond uniquement aux mots entiers, par exemple. la position après le mot "sable" ne serait pas une correspondance simplement parce qu'elle est précédée de "et".

L'espace devant le "ou" dans l'assertion de largeur nulle est nécessaire pour en faire une longueur fixe. Essayez si cela résout déjà votre problème.

EDIT: appliqué à la chaîne "à l'exception des mots AND, OR et NOT." en tant que remplacement global par des guillemets simples, cela retourne:

'except' 'the' 'words' AND, OR and NOT.
14
Tomalak

John,

La regex dans votre question est presque correcte. Le seul problème est que vous mettez le lookahead à la fin de la regex plutôt qu'au début. En outre, vous devez ajouter des limites de mot pour forcer l'expression régulière à correspondre à des mots entiers. Autrement, les mots "nd" dans "et", "r" dans "ou", etc., correspondront, car "nd" et "r" ne sont pas dans votre aspect négatif.

(? i)\b (?! et | pas | ou) (? [a-z0-9] +)\b

5
Jan Goyvaerts

Appelez-moi fou, mais je ne suis pas fan de la lutte contre la regex; Je limite mes modèles à des choses simples que je peux comprendre et triche souvent pour le reste - par exemple via une variable MatchEvaluator:

    string[] whitelist = new string[] { "and", "not", "or" };
    string input = "foo and bar or blop";
    string result = Regex.Replace(input, @"([a-z0-9]+)",
        delegate(Match match) {
            string Word = match.Groups[1].Value;
            return Array.IndexOf(whitelist, Word) >= 0
                ? Word : ("\"" + Word + "\"");
        });

(édité pour une mise en page plus concise)

3
Marc Gravell

Basé sur la réponse de Tomalaks:

(?<!and|or|not)\b(?!and|or|not)

Cette regex a deux problèmes:

  1. (?<! ) ne fonctionne que pour le regard en longueur fixe

  2. La regex précédente ne visait que la fin/le début des mots qui l'entourent, pas le mot entier.

(?<!\band)(?<!\bor)(?<!\bnot)\b(?!(?:and|or|not)\b)

Cette regex corrige les deux problèmes ci-dessus. Tout d'abord, divisez le regard en trois parties distinctes. Deuxièmement, en ajoutant des limites de mots (\b) dans les contours.

2
Markus Jarderot
(?!\bnot\b|\band\b|\bor\b|\b\"[^"]+\"\b)((?<=\s|\-|\(|^)[^\"\s\()]+(?=\s|\*|\)|$))

J'utilise cette regex pour trouver tous les mots qui ne sont pas entre guillemets ou sont les mots "pas" "et" ou "ou".

0
CharlesF