Reputation: 29966
Since Java 7, named capture groups have been supported. However, the built-in Clojure functions re-matches
, re-find
, and re-groups
do not allow access to the capture groups by name.
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(dotest
; Define a phone number pattern with some named capture groups.
; The reader literal #"..." allows us to avoid double-backslash like
; we'd need if using the form `(re-pattern <string>)`
(let [patt #"(?<area>\d{3})-(?<prefix>\d{3})-(?<tail>\d{4})"]
(is= java.util.regex.Pattern (type patt))
; `re-matches` will find the capture groups and stick them in a vector
; after the full match The capture groups are numbered starting with 1.
; The full match is like group zero.
(is= ["619-239-5464" "619" "239" "5464"] (re-matches patt "619-239-5464"))
; Construct a java.util.regex.Matcher. Keep in mind that it is a mutable object!
(let [matcher (re-matcher patt "619-239-5464")]
; Execute the Matcher via `re-find`. It returns all 4 groups and caches them
(is= ["619-239-5464" "619" "239" "5464"] (re-find matcher))
; `re-groups` simply returns the cached result from the Matcher
(is= ["619-239-5464" "619" "239" "5464"] (re-groups matcher))
How can I use named capture groups in a regex from Clojure?
Upvotes: 2
Views: 267
Reputation: 29966
The class java.util.regex.Matcher
supports named capture groups, but you need to use Java interop to get at them. An example:
; We need the instance function Matcher.group( <name> ) to extract named groups
(is= "619" (.group matcher "area"))
(is= "239" (.group matcher "prefix"))
(is= "5464" (.group matcher "tail"))))
The above code is based on this template project.
Upvotes: 3