# Best way to get all substrings or numbers matching a regex

**URL:** https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571
**Category:** General Usage
**Tags:** strings, regex, parsing
**Created:** [November 27, 2019, 11:05am UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571 "2019-11-27T11:05:47Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Maurice\_Diamantini](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurice_diamantini/32/3676_2.png) [@Maurice\_Diamantini](https://discourse.julialang.org/u/Maurice_Diamantini)
#### Post date: [November 27, 2019, 11:05am UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/1 "2019-11-27T11:05:47Z")

</div>

Bonjour,

What is the best way for getting a String on Number Vector from a regex (like with the old matchall method)?

```julia
pat = r"[+-]?\d+\.?\d*"
txt = "aaa -1 bbb +2.2 ccc 123.456 ddd"

# findall?
ranges = findall(pat, txt)
words = map(range->txt[range], ranges) # could be shorter?
numbers = parse.(Float64, words)
# =>
# 3-element Array{Float64,1}:
# 1.0  
# -1.0  
# 123.456

# eachmatch?
matches = eachmatch(pat, txt)
words = getfield.(matches, :match)
numbers = parse.(Float64, words)
# => idem (ok)

# versus matchall or getall or... (;-)
numbers = parse.(Float64, matchall(pat, txt))

```

– Maurice

---

<div class="post-metadata">

### Author: ![BeastyBlacksmith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/beastyblacksmith/32/4741_2.png) [@BeastyBlacksmith](https://discourse.julialang.org/u/BeastyBlacksmith)
#### Post date: [November 27, 2019, 11:30am UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/2 "2019-11-27T11:30:03Z")

</div>

Whats about `numbers = parse.(Float64, [match.match for match in eachmatch(pat, txt)])`

---

<div class="post-metadata">

### Author: ![Maurice\_Diamantini](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurice_diamantini/32/3676_2.png) [@Maurice\_Diamantini](https://discourse.julialang.org/u/Maurice_Diamantini)
#### Post date: [November 27, 2019, 1:03pm UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/3 "2019-11-27T13:03:34Z")

</div>

Yes thank you, but I feel that:

```julia
words = [match.match for match in eachmatch(pat, txt)]

```

is not really better than:

```julia
words = getfield.(eachmatch(pat, txt), :match)

```

(neither is the `collect()` version)

Ruby has a scan method which allow to write:

```julia
txt = "aaa -1 bbb +2.2 ccc 123.456 ddd"
words = txt.scan(/[+-]?\d+\.?\d*/)

```

witch would allow in Julia:

```julia
numbers = parse.(Float64, scan(pat, txt))

```

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [November 27, 2019, 1:07pm UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/4 "2019-11-27T13:07:11Z")

</div>

> [@Maurice\_Diamantini](#):
>
> What is the best way

Those all seem like good ways - what’s your criteria for “best”? If performance, you can check with BenchmarkTools. If you mean stylistically, that’s more about your own preference. In my own code, I had a similar problem and did

```julia
numbers = map(eachmatch(pat, text)) do m
    parse(Float64, m.match)
end

```

Since it does it in one step without intermediate variables, but to me, it’s clearer than the broadcast or anonymous function versions. I don’t think any of these is more or less idiomatic Julia though.

Side note - I had to account for numbers like “1.233e5” in my code, which wouldn’t be matched by your regex. Maybe this doesn’t occur in your input, but I thought I’d mention it

---

<div class="post-metadata">

### Author: ![Maurice\_Diamantini](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurice_diamantini/32/3676_2.png) [@Maurice\_Diamantini](https://discourse.julialang.org/u/Maurice_Diamantini)
#### Post date: [November 27, 2019, 1:26pm UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/5 "2019-11-27T13:26:18Z")

</div>

> [@kevbonham](#):
>
> Those all seem like good ways - what’s your criteria for “best”,  
> performance?, stylistically?, …?

My question was not about performances, but rather about shortness, readability and stylistic. I agree that your solution is a good candidat, but I would have liked another solution to be possible for getting all words.  
The incomplete regex for Float was just an example, the question was mainly about getting all words in some text from a rexex.

– Maurice

---

<div class="post-metadata">

### Author: ![anon56330260](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@anon56330260](https://discourse.julialang.org/u/anon56330260)
#### Post date: [November 27, 2019, 1:44pm UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/6 "2019-11-27T13:44:14Z")

</div>

I think the problem here is that `eachmatch` can’t be combined well with broadcast and parse, because ` eachmatch` will return `Base.RegexMatchIterator`, which iterates through Regexmatch instead of directing returning the contents, so it can’t be passed to `parse`. Maybe you can define a new iterator which wraps Regexmatch and returns what you want, or you can find some other regex libraries and implement what you want in Julia?

---

<div class="post-metadata">

### Author: ![Maurice\_Diamantini](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurice_diamantini/32/3676_2.png) [@Maurice\_Diamantini](https://discourse.julialang.org/u/Maurice_Diamantini)
#### Post date: [November 27, 2019, 2:32pm UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/7 "2019-11-27T14:32:54Z")

</div>

If broadcating element Array access would be allowed

```julia
ranges = findall(pat, txt)
word1 = txt[ranges[1]]
# => ok
words = txt.[ranges]
# => error ; no broadcast with .[]

```

We could write

```julia
numbers = parse.(Float64, txt.[findall(pat, txt)])

```

If broadcating field access would be allowed

```julia
matches = collect( eachmatch(pat, txt) )
word1 = matches[1].match
# => ok
words = getfield.(matches, :match)
# => ok
words = matches..match
# => error ; no broadcast with ..

```

We could write

```julia
numbers = parse.(Float64, eachmatch(pat, txt)..match )

```

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [November 27, 2019, 3:23pm UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/8 "2019-11-27T15:23:57Z")

</div>

You could just roll your own:

```julia
julia> rubyscan(pat, str) = (m.match for m in eachmatch(pat, str)) # wrapping in parentheses instead of brackets so it doesn't allocate
rubyscan (generic function with 1 method)

julia> pat = r"[+-]?\d+\.?\d*"
r"[+-]?\d+\.?\d*"

julia> txt = "aaa -1 bbb +2.2 ccc 123.456 ddd"
"aaa -1 bbb +2.2 ccc 123.456 ddd"

julia> parse.(Float64, rubyscan(pat, txt))
3-element Array{Float64,1}:
  -1.0
   2.2
 123.456

```

---

<div class="post-metadata">

### Author: ![Maurice\_Diamantini](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurice_diamantini/32/3676_2.png) [@Maurice\_Diamantini](https://discourse.julialang.org/u/Maurice_Diamantini)
#### Post date: [November 27, 2019, 3:47pm UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/9 "2019-11-27T15:47:21Z")

</div>

> [@kevbonham](#):
>
> # wrapping in parentheses instead of brackets so it doesn’t allocate  
> rubyscan(pat, str) = (m.match for m in eachmatch(pat, str))  
> pat = r"[±]?\d+.?\d\*" r"[±]?\d+.?\d\*"  
> txt = “aaa -1 bbb +2.2 ccc 123.456 ddd”  
> parse.(Float64, rubyscan(pat, txt))

Yes, but it’s not shorter since you have te define the rubyscan method first 🙂 _(and thank you for your parentheses tip)_

If one has to explain the code to someboby else, your three lines solution (post4) is yet the best one _(with eachmatch replaced by findall, although findall is julia-1.3+ only)_.

```julia
numbers = map(findall(pat, txt)) do range
    parse(Float64, txt[range])
end

```

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [November 27, 2019, 3:56pm UTC](https://discourse.julialang.org/t/best-way-to-get-all-substrings-or-numbers-matching-a-regex/31571/10 "2019-11-27T15:56:07Z")

</div>

```julia
numbers = [parse(Float64, m.match) for m in eachmatch(pat, txt)]

```

?
