2008-10-16 5 views
6

Que dois-je utiliser pour rechercher plusieurs mots dans une chaîne? Je voudrais que l'opération logique soit ET que tous les mots soient dans la chaîne quelque part. J'ai un tas de paragraphes absurdes et un paragraphe en anglais, et je voudrais le préciser en spécifiant quelques mots communs comme, "the" et "and", mais je voudrais qu'il corresponde à tous les mots que je spécifie.Recherche multi-mots Regex

Répondre

2

Peut-être en utilisant un language recognition chart reconnaître anglais fonctionnerait. Certains tests rapides semblent fonctionner (ceci suppose que les paragraphes sont séparés par des retours à la ligne uniquement). L'expression rationnelle correspondra à l'une de ces conditions ... \ bword \ b est un mot séparé par des limites. Le mot \ b est une terminaison de mot et juste le mot correspondra à n'importe quel endroit du paragraphe à apparier.

my @paragraphs = split(/\n/,$text); 
for my $p (@paragraphs) { 
    if ($p =~ m/\bthe\b|\band\b|\ban\b|\bin\b|\bon\b|\bthat\b|\bis\b|\bare\b|th|sh|ough|augh|ing\b|tion\b|ed\b|age\b|’s\b|’ve\b|n’t\b|’d\b/) { 
     print "Probable english\n$p\n"; 
    } 
} 
+0

Je ne recommanderais pas 'on' pour détecter l'anglais. Cela signifie "il" dans de nombreuses langues slaves (comme je suis sûr que Vinko sait;) –

+0

url a déménagé: http://en.wikipedia.org/wiki/Wikipedia:Language_recognition_chart#English –

0

En supposant que PCRE (Perl regexes), je ne suis pas sûr que vous pouvez le faire du tout facilement. L'opération AND est une concaténation de regex, mais vous voulez pouvoir permuter l'ordre dans lequel les mots apparaissent sans avoir à générer formellement la permutation. Pour N mots, quand N = 2, c'est supportable; avec N = 3, c'est à peine OK; avec N> 3, il est peu probable qu'il soit acceptable. Ainsi, la solution itérative simple - N regexes, un pour chaque mot, et itérer assurant que chacun est satisfait - semble être le meilleur choix pour moi.

+0

Pourquoi les N objets doivent-ils être des expressions rationnelles? Pourrait juste utiliser "index" ici. –

+1

\ b (foo | bar | baz) \ b. * \ B (?! \ 1) (foo | bar | baz) \ b. * \ B (?! \ 1) (?! \ 2) (foo | bar | baz) \ b devrait gérer les permutations en utilisant des références arrières et un lookahead négatif pour éviter de faire correspondre un mot deux fois. C'est toujours proprement diabolique, mais au moins la longueur du motif n'est pas O (N! – stevemegson

+0

@BKB: Je ne suis pas sûr de ce que vous voulez dire en utilisant un index. –

2

Tout d'abord je ne suis pas certain de ce que vous essayez de retourner ... toute la phrase? Les mots entre vos deux mots donnés?

Quelque chose comme:

\b(word1|word2)\b(\w+\b)*(word1|word2)\b(\w+\b)*\. 

(où \b est la limite de mot dans votre langue) sélectionnne une phrase complète qui contenait l'une des deux mots ou les deux ..

Vous auriez probablement besoin de le rendre insensible à la casse de sorte que, s'il apparaît au début de la phrase, il apparaisse toujours

+0

Cela ne correspond-il pas à une phrase qui contient deux mots, word1 suivi de word2, ou word2 suivi de word1 (comme vous le souhaitez), ou word1 suivi de word1, ou word2 suivi de word2 (non désiré)? C'était le genre de problème que j'ai rencontré en essayant de répondre. –

2

AND comme concaténation

^(?=.*?\b(?:word1)\b)(?=.*?\b(?:word2)\b)(?=.*?\b(?:word3)\b) 

OR en alternance

^(?=.*?\b(?:word1|word2|word3)\b 
^(?=.*?\b(?:word1)\b)|^(?=.*?\b(?:word2)\b)|^(?=.*?\b(?:word3)\b) 
11

Les expressions régulières prennent en charge une condition « lookaround » qui vous permet de rechercher un terme dans une chaîne, puis oublier l'emplacement du résultat; en commençant au début de la chaîne pour le terme de recherche suivant. Cela permettra de rechercher une chaîne pour un groupe de mots dans n'importe quel ordre.

L'expression régulière pour cela est:

^(?=.*\bword1\b)(?=.*\bword2\b)(?=.*\bword3\b) 

\b est une limite de mot et le ?= est le modificateur de lookaround.

Si vous avez un nombre variable de mots que vous souhaitez rechercher, vous devrez construire cette chaîne d'expression régulière avec une boucle - enroulez chaque mot dans la syntaxe lookaround et ajoutez-le à l'expression.

+0

Exactement ce dont j'avais besoin. Notez qu'il manque quelques astérisques ci-dessus. Chaque section devrait être '(? =. * \ Bword \ b)' – Tamlyn

+0

Les astérisques étaient là, mais ils étaient traités comme des balises. Je l'ai corrigé en appliquant le formatage du code. –

Questions connexes