Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clojure regex named groups

Tags:

regex

clojure

I have a problem with re-find in clojure. Actually I'm doing

(re-find #"-(?<foo>\d+)-(?<bar>\d+)-(?<toto>\d+)-\w{1,4}$" 
"http://www.bar.com/f-a-c-a-a3-spok-ser-2-phse-2-1-6-ti-105-cv-9-31289-824-gu" )

My result is fine:

["-9-31289-824-gt" "9" "31289" "824"]

But I would prefer to have a hash looking like:

{:foo "9" :bar "31289" :toto "824"}

I have understood that java.util.regex.Matcher/group is doing something like that but I haven't been able to use it correctly. Thanks for your help

like image 349
Elie Ladias Avatar asked Sep 17 '14 13:09

Elie Ladias


2 Answers

The java regex library Clojure is built against (Java 1.6) doesn't support regex named capturing groups.

However, you can use Clojure's zipmap function to combine name keys and re-find's captured groups into a map. Groups that aren't matched will get a nil value for the name key.

(zipmap [:foo :bar :toto]
        (rest (re-find #"-(\d+)-(\d+)-(\d+)-\w{1,4}$" 
                        "http://www.bar.com/f-a-c-a-a3-spok-ser-2-phse-2-1-6-ti-105-cv-9-31289-824-gu")))

=> {:foo "9" :bar "31289" :toto "824"}
like image 133
NielsK Avatar answered Sep 29 '22 03:09

NielsK


JDK didn't support named capture groups until JDK 7.

Here's announcement on oracle blog

Quote:

This convenient feature has been missed in Java RegEx for years, now it finally got itself in JDK7 b50.

Since clojure supports JDK >= 6 you're out of luck if you're looking for something native (clojure uses java regex Patterns and Matchers behind the scenes).

You can always use external libraries, like named-re. That one gives you exactly what you need.

Calling

(require 'named-re.core)
(re-find #"-(?<foo>\d+)-(?<bar>\d+)-(?<toto>\d+)-\w{1,4}$" 
     "http://www.bar.com/f-a-c-a-a3-spok-ser-2-phse-2-1-6-ti-105-cv-9-31289-824-gu" )

will return

{:toto "824", :bar "31289", :foo "9", :0 "-9-31289-824-gu"}
like image 40
soulcheck Avatar answered Sep 29 '22 03:09

soulcheck