2009-03-30 4 views
13

Je dois créer une expression régulière qui peut correspondre à plusieurs chaînes. Par exemple, je veux trouver toutes les instances de «bon» ou «excellent». J'ai trouvé quelques exemples, mais ce que je suis venu avec ne semble pas fonctionner:Regex pour faire correspondre plusieurs chaînes

\b(good|great)\w*\b 

Quelqu'un peut-il me diriger dans la bonne direction?

Editer: Je devrais noter que je ne veux pas simplement faire correspondre des mots entiers. Par exemple, je pourrais vouloir faire correspondre «ood» ou «reat» (parties de mots).

Éditer 2: Voici un exemple de texte: "C'est une très bonne histoire." Je pourrais vouloir faire correspondre "ceci" ou "vraiment", ou je pourrais vouloir faire correspondre "eall" ou "reat".

+1

Voulez-vous également faire correspondre "oo", "o" ou "t"? – jpalecek

+3

Qu'en est-il de ooooooooooooooooooooooooooooooooooooo? –

+0

J'ai trouvé qu'en utilisant "bon | bon" comme le modèle fonctionne, est-ce correct? Pourquoi les exemples de certaines personnes ont-ils plus de balisage? –

Répondre

21

Si vous ne pouvez garantir qu'il n'y a pas de caractères regex réservés dans votre liste de mots (ou si vous leur échapper), vous pouvez simplement utiliser ce code pour faire a big word list en @"(a|big|word|list)". Il n'y a rien de mal avec l'opérateur | pendant que vous l'utilisez, tant que ces () l'entourent. Cela ressemble à \w* et les modèles \b sont ce qui interfèrent avec vos matchs.

String[] pattern_list = whatever; 
String regex = String.Format("({0})", String.Join("|", pattern_list)); 
+1

possible une erreur: Il devrait être String.Join ("|", word_list) plutôt que String.Join (word_list, "|"), vous pouvez aussi consulter http://msdn.microsoft.com/en-us/library/57a79xd0 .aspx – David

+0

Bonne prise - merci! J'ai mis à jour ma réponse. – ojrac

+1

Contrairement à la question, il ne correspondra pas par exemple à '' ood ''dans' 'good''. – MikeM

4
(good)*(great)* 

après votre édition:

\b(g*o*o*d*)*(g*r*e*a*t*)*\b 
+0

Est-ce pas ooooooooooooooooooooooooooooooooooooooooddddddddddddddddddddddddddddd match? –

+0

Oui, avec "gore", "gogogo", et un tas d'autres combinaisons involontaires. – Randy

0

Je ne comprends pas le problème correctement:

Si vous voulez faire correspondre « grand » ou « REAT » vous pouvez exprimer par un modèle comme:

"g?reat" 

Ce simple dit que la "reat" -part doit exister et le "g" est optionnel. Cela correspondrait à "reat" et "great" mais pas à "eat", car le premier "r" dans "reat" est requis.

Si vous avez les aussi les mots « grand » et « bon » et que vous voulez les faire correspondre à la fois avec un « g » en option, vous pouvez écrire comme ceci:

(g?reat|g?ood) 

Et si vous voulez inclure un mot-limite comme:

\b(g?reat|g?ood) 

vous devez savoir que cela ne correspondrait pas à quelque chose comme « breat » parce que vous avez le « rande » mais le « r » est pas à la limite de mot en raison de la « b ".

Donc, si vous voulez faire correspondre des mots entiers qui contiennent un lien sous-chaîne « de rande » ou « ood » alors vous devriez essayer:

"\b\w*?(reat|ood)\w+\b" 

Ce lit: 1. En commençant par un début correspondant à une limite de mot nombre de mots-caractères, mais ne soyez pas grognon. 2. Faites correspondre "reat" ou "ood" pour que seuls les mots qui correspondent à l'un d'entre eux correspondent. 3. Faites correspondre tout nombre de caractères de mot après "reat" ou "ood" jusqu'à ce que la limite de mot suivante soit atteinte.

Cela correspondra:

« bonté », « bon », « ood » (si un mot complet)

Il peut être lu comme: Donnez-moi tous les mots complets qui contiennent « ood » ou "reat".

Est-ce ce que vous cherchez?

1

Je ne suis pas entièrement sûr que regex seul offre une solution pour ce que vous essayez de faire. Vous pouvez toutefois utiliser le code suivant pour créer une expression regex pour un mot donné. Bien que, le motif regex résultant a le potentiel de devenir très long et lent:

function wordPermutations($word, $minLength = 2) 
{ 
    $perms = array(); 

    for ($start = 0; $start < strlen($word); $start++) 
    { 
     for ($end = strlen($word); $end > $start; $end--) 
     { 
      $perm = substr($word, $start, ($end - $start)); 

      if (strlen($perm) >= $minLength) 
      { 
       $perms[] = $perm; 
      } 
     } 
    } 

    return $perms; 
} 

Code d'essai:

$perms = wordPermutations('great', 3); // get all permutations of "great" that are 3 or more chars in length 
var_dump($perms); 

echo ('/\b('.implode('|', $perms).')\b/'); 

Résultat:

array 
    0 => string 'great' (length=5) 
    1 => string 'grea' (length=4) 
    2 => string 'gre' (length=3) 
    3 => string 'reat' (length=4) 
    4 => string 'rea' (length=3) 
    5 => string 'eat' (length=3) 

/\b(great|grea|gre|reat|rea|eat)\b/ 
1

Je pense que vous demandent pour vous que vous ne voulez pas dire si vous voulez chercher une partie de t il mot, vous littéralement recherche des lettres

par exemple. Recherche {Jack, Jim} dans "John et Shelly sont cool"

est à la recherche toutes les lettres dans les noms {J, a, c, k, i, m}

* J * Ohn * un * e Shelly * a * re

et que vous n'avez pas besoin REG-EX :)

à mon avis, a Suffixe arbre peut vous aider avec cette

http://en.wikipedia.org/wiki/Suffix_tree#Functionality

appréciez.

1

Vérifiez simplement la valeur booléenne renvoyée par Regex.IsMatch().

if (Regex.IsMatch(line, "condition") && Regex.IsMatch(line, "conditition2")) 

La ligne aura les deux regex, à droite.

+0

La liste peut contenir beaucoup plus de deux mots, et cette approche ne s'adapte pas bien. En outre, je pense que vous devez seulement correspondre à l'un des mots, ce qui signifie que votre '&&' devrait être '||'. La réponse elle-même avait de nombreux problèmes avec le formatage, la syntaxe et l'orthographe, que j'ai tenté de corriger. S'il vous plaît examiner mes changements. –

Questions connexes