2010-10-18 15 views
9

Peut-être que je vais à ce sujet tout faux, mais j'essaie d'obtenir tous les matches dans une chaîne pour un motif regex particulier. J'utilise re-matcher pour obtenir un objet Match, que je passe à re-find, en me donnant (full-string-match, grouped-text) des paires. Comment aurais-je une séquence de toutes les correspondances produites par l'objet Match?Clojure: obtenir la liste des correspondances regex

Dans Clojuresque Python, il ressemblerait à ceci:

pairs = [] 
match = re-matcher(regex, line) 

while True: 
    pair = re-find(match) 
    if not pair: break 
    pairs.append(pair) 

Toutes les suggestions?

Répondre

21

Vous souhaitez probablement utiliser le re-seq intégré et le littéral regex intégré de Clojure. Ne jouez pas avec les objets java sous-jacents sauf si vous en avez vraiment besoin.

(doc re-seq) 


clojure.core/re-seq 
([re s]) 
    Returns a lazy sequence of successive matches of pattern in string, 
    using java.util.regex.Matcher.find(), each such match processed with 
    re-groups. 

For example:

user> (re-seq #"the \w+" "the cat sat on the mat") 
("the cat" "the mat") 

In answer to the follow-up comment, group captures will result in a vector of strings with an element for each part of the group in a match:

user> (re-seq #"the (\w+(t))" "the cat sat on the mat") 
(["the cat" "cat" "t"] ["the mat" "mat" "t"]) 

You can extract a specific element by taking advantage of the elegant fact that vectors are functions of their indices.

user> (defn extract-group [n] (fn [group] (group n))) 
#'user/extract-group 
user> (let [matches (re-seq #"the (\w+(t))" "the cat sat on the mat")] 
     (map (extract-group 1) matches)) 
("cat" "mat") 

Or you can destructure the matches (here using a for macro pour aller sur tous les matches, mais cela pourrait aussi se faire dans un argument let ou fonction de liaison):

user> (dorun 
     (for [[m1 m2 m3] (re-seq #"the (\w+(t))" "the cat sat on the mat")] 
      (do (println "m1:" m1) 
       (println "m2:" m2) 
       (println "m3:" m3)))) 
m1: the cat 
m2: cat 
m3: t 
m1: the mat 
m2: mat 
m3: t 
+0

C'est ce que je cherche, mais je reçois un résultat différent: un vecteur de listes, pas un vecteur de chaînes. – exupero

+0

Voulez-vous dire une «séquence de vecteurs»? C'est ce qui serait retourné si vous avez une capture de groupe dans votre regex. J'ai ajouté quelques exemples ci-dessus. –

+0

Vous avez raison: je devais dire «séquence de vecteurs». Vos exemples ont éclairci les choses pour moi. Merci. – exupero