1
votes

I'm trying to match a pattern at a certain position k (k=3 in the example below) in a string.

I've tried

(re-seq #"^alex" (str (drop 3 "xxxalexandre")))

but it does not match anything (=> nil)

What is the Clojure-way to do this ? (I'm on Clojure 1.4.0)

A good alternative would be to match the pattern anywhere, but then I would need the position where it found the pattern in the input. Can I do this without accessing the java.util.regex.Matcher instance ? (which I've been told is very bad, since it's mutable)

3

3 Answers

5
votes

The expression (str (drop 3 ... should be (apply str (drop 3 ....

But, better would be to use subs:

user=> (re-seq #"^alex" (subs "xxxalexandre" 3))
("alex")

Or, if you like, go in three characters in your regular expression:

user=> (map second (re-seq #"^...(alex)" "xxxalexandre"))
("alex")

For your follow-up, finding the location of the match, one way (for simple cases) would be to use .indexOf on the result:

user=> ((fn [s p] (let [[m] (re-seq p s)] [m (.indexOf s m)])) "xxxalexandre" #"alex")
["alex" 3]
4
votes

Try see what (str (drop 3 "xxxalexandre")) returns:

=> (str (drop 3 "xxxalexandre"))
"clojure.lang.LazySeq@a65bc80b"

Since drop returns a lazy sequence, the arguments of str is a lazy sequence, and what's returned is the .toString of that lazy sequence, namely a string of the object reference.

=> (drop 3 "xxxalexandre")
(\a \l \e \x \a \n \d \r \e)

=> (str (lazy-seq `(\a \l \e \x \a \n \d \r \e)))
"clojure.lang.LazySeq@a65bc80b"

Use apply to realize the lazy seq and put the collection into the str function as multiple arguments.

=> (apply str (lazy-seq '(\a \l \e \x \a \n \d \r \e)))
"alexandre"

=> (apply str (drop 3 "xxxalexandre"))
"alexandre"

Now your regex wil match:

=> (re-seq #"^alex" (apply str (drop 3 "xxxalexandre")))
("alex")
2
votes

$ in regex maps to the end of a line.. you probably want ^alex