2014-01-28 3 views
1

Каков оптимальный способ соединения нескольких регулярных выражений в функции Clojure? Я считаю, что функция будет начать, как, например:Несколько регулярных выражений в Clojure

(defn foo [x] 
(re-seq #"some means to combine multiple regex") 

, но я не ясно, если это будет работать, или эффективность такой функции. Чтобы представить пример возможной связи с регулярным выражением, можно рассмотреть функцию, которая искала как доменные имена, так и IP. Для доменных имен я хотел бы использовать регулярное выражение, как, например:

(re-seq #"\b([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}\b" x) 

и для IP:

(re-seq #"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b") 

ответ

6

Regexs уже позволяет чередование с оператором |.

user=> (re-seq #"\d+" "123 foo 345 bar") 
("123" "345") 
user=> (re-seq #"[a-zA-Z]+" "123 foo 345 bar") 
("foo" "bar") 
user=> (re-seq #"\d+|[a-zA-Z]+" "123 foo 345 bar") 
("123" "foo" "345" "bar") 

Вы можете программно объединение регулярных выражений шаблонов при желании вставляя оператора |.

(defn union-re-patterns [& patterns] 
    (re-pattern (apply str (interpose "|" (map #(str "(" % ")") patterns))))) 

user=> (union-re-patterns #"\d+" #"[a-zA-Z]+") 
#"(\d+)|([a-zA-Z]+)" 
user=> (map first (re-seq (union-re-patterns #"\d+" #"[a-zA-Z]+") "123 foo 345 bar")) 
("123" "foo" "345" "bar") 
+2

Это работает большую часть времени, но что, если один из шаблонов использует пронумерованный захватывая группу? например, '(.) \ 1 {5}', для сопоставления любого символа шесть раз подряд? Добавленные парны, которые вы добавили, испортили нумерацию групп; вам нужно использовать '(?:', а не просто '('. – amalloy

4

В зависимости от вашего варианта использования frak может быть тем, что вы ищете; Frak преобразует коллекции строк в регулярных выражений для сопоставления этих строк:

(frak/pattern ["foo" "bar" "baz" "quux"]) 
;; => #"(?:ba[rz]|foo|quux)" 
Смежные вопросы