2009-06-18 6 views
3

J'ai été sur celui-ci pendant un moment et ne peux pas sembler fonctionner. Voici ce que j'essaie de faire. Étant donné trois mots word1, word2 et word3, je voudrais construire une regex qui les appariera dans cet ordre, mais avec un ensemble de mots potentiels entre eux (sauf une nouvelle ligne).RegEx - Faire correspondre un ensemble de mots

Par exemple, si j'avais les suivantes:

word1 = what 
word2 = the 
word3 = hell 

je voudrais correspondre aux chaînes suivantes, avec une seule:

"what the hell" 
"what in the hell" 
"what the effing hell" 
"what in the 9 doors of hell" 

Je pensais que je pouvais faire ce qui suit (ce qui permet pour que 0 à 5 mots existent entre chaque variable de mot):

regex = "\bword1(\b\w+\b){0,5}word2(\b\w+\b){0,5}word3\b" 

Hélas, non, cela ne fonctionne pas. Il est important que j'ai un moyen de spécifier une distance de m à n mots entre les mots (où m toujours < n).

Répondre

1
$ cat try 
#! /usr/bin/perl 

use warnings; 
use strict; 

my @strings = (
    "what the hell", 
    "what in the hell", 
    "what the effing hell", 
    "what in the 9 doors of hell", 
    "hello", 
    "what the", 
    " what the hell", 
    "what the hell ", 
); 

for (@strings) { 
    print "$_: ", /^what(\s+\w+){0,5}\s+the(\s+\w+){0,5}\s+hell$/ 
        ? "match\n" 
        : "no match\n"; 
} 

$ ./try 
what the hell: match 
what in the hell: match 
what the effing hell: match 
what in the 9 doors of hell: match 
hello: no match 
what the: no match 
what the hell: no match 
what the hell : no match 
+0

Ceci est le plus élégant jusqu'à présent, et il fonctionne comme annoncé, mais il existe des sous-matches. Dis-moi, est-ce que je m'en soucie? Je me soucie le plus que toute la chaîne est assortie de word1 à l'avant, word2 quelque part au milieu et word3 à la fin ("quelque part au milieu" est le mot problème de distance). –

+0

C'est aussi simple que d'ajouter des ancres au motif. Modifié! –

+0

Vous ne devriez pas se soucier des sous-matches. Vous pouvez toujours obtenir toute la chaîne qui correspond. En python, que vous mentionnez ci-dessous, vous le faites via matchobj.group (0). Si vous êtes opposé à ce que des sous-groupes se produisent, il suffit de passer tous les parenthèses de (\ s + \ w +) à (?: \ S + \ w +) pour qu'ils n'attrapent pas un sous-groupe. – Clint

2

"\bwhat(\s*\b\w*\b\s*){0,5}the(\s*\b\w*\b\s*){0,5}hell" fonctionne pour moi (en Ruby)

list = ["what the hell", "what in the hell", "what the effing hell", 
    "what in the 9 doors of hell", "no match here hell", "what match here hell"] 

list.map{|i| /\bwhat(\s*\b\w*\b\s*){0,5}the(\s*\b\w*\b\s*){0,5}hell/.match(i) } 
=> [#<MatchData:0x12c4d1c>, #<MatchData:0x12c4d08>, #<MatchData:0x12c4cf4>, 
    #<MatchData:0x12c4ce0>, nil, nil] 
+0

Ceci correspond à la fois à la phrase entière et renvoie un résultat de '' pour le groupe (1). J'ai aussi essayé (\ s * \ w * \ s *) {0,5} avec le même résultat. C'est beaucoup plus loin que ce que j'ai obtenu par moi-même! Aucune suggestion? Je fais ça en Python, au cas où ça compte. –

0

Works pour moi dans Clojure:

(def phrases ["what the hell" "what in the hell" "what the effing hell" 
       "what in the 9 doors of hell"]) 

(def regexp #"\bwhat(\s*\b\w*\b\s*){0,5}the(\s*\b\w*\b\s*){0,5}hell") 

(defn valid? [] 
    (every? identity (map #(re-matches regexp %) phrases))) 

(valid?) ; <-- true 

selon le modèle de Ben Hughes.

Questions connexes