Parsing values from string into struct using match in Julia My goal
I am parsing from a string which contains token:value pairs into a type.
Example:
mutable struct Foo
    bar
    baz
    qux
end

function parse(str::AbstractString)::Foo
    f = Foo()

    bar_pattern = r&quot;bar:(\w*)&quot;
    baz_pattern = r&quot;baz:(\d*)&quot;
    qux_pattern = r&quot;qux:(\w*)&quot;

    f.bar = match(bar_pattern, s)[1]
    f.baz = match(baz_pattern, s)[1]
    f.qux = match(qux_pattern, s)[1]

    return d
end


Problem
This works but only if the patterns are actually present. When match can't find the pattern, it returns nothing, which of course can't be indexed [1] or accessed with captures. The result is an error.
I want the fields of the returned struct to either get the matched result (the &quot;capture&quot;) directly, or remain empty or set to nothing, should the match be unable to find the pattern.
I could do something like this:
function safeparse(str::AbstractString)::Foo
    f = Foo()

    bar_pattern = r&quot;bar:(\w*)&quot;
    baz_pattern = r&quot;baz:(\d*)&quot;
    qux_pattern = r&quot;qux:(\w*)&quot;

    if !isnothing(match(bar_pattern, s))
        f.bar = match(bar_pattern, s)[1]
    end

    if !isnothing(match(baz_pattern, s))
        f.baz = match(baz_pattern, s)[1]
    end

    if !isnothing(match(qux_pattern, s))
        f.qux = match(qux_pattern, s)[1]
    end

    return f
end

But that approach seems ugly and becomes verbose very quick if more/new patterns are introduced.
Question
Is there a nicer but readable way to achieve this?
Preferably without combining/changing the regex patterns or too much regex magic, however I am
open to that route too if it is the only nice (less verbose) way. I am of course also open to general tips.
To keep things simple, just assume that the patterns my example is looking for only appear 0 or 1 times. However if the only way to make this nicer involves writing another function like safematch which does the check for nothing and returns the captured value or nothing, I would want that to also work with multiple matches somehow and stay a bit more general.
The easiest thing I can think of is to use eachmatch -- when there is no match at all, it returns an empty iterator:
julia&gt; collect(eachmatch(r&quot;(bar:(\w*))&quot;, &quot;bla bar:werfsd 1223 bar:skdf&quot;))
2-element Array{RegexMatch,1}:
 RegexMatch(&quot;bar:werfsd&quot;, 1=&quot;bar:werfsd&quot;, 2=&quot;werfsd&quot;)
 RegexMatch(&quot;bar:skdf&quot;, 1=&quot;bar:skdf&quot;, 2=&quot;skdf&quot;)

julia&gt; collect(eachmatch(r&quot;(bar:(\w*))&quot;, &quot;bla &quot;))
RegexMatch[]

Then you can simply combine those into a dictionary, for example:
julia&gt; Dict(re =&gt; [m[1] for m in eachmatch(re, s)] for re in patterns)
Dict{Regex,Array{T,1} where T} with 3 entries:
  r&quot;qux:(\w*)&quot; =&gt; Union{Nothing, SubString{String}}[]
  r&quot;baz:(\d*)&quot; =&gt; SubString{String}[&quot;33&quot;]
  r&quot;bar:(\w*)&quot; =&gt; SubString{String}[&quot;werfsd&quot;, &quot;skdf&quot;]

Without further information about how you want to organize your data structure when more then one value occurs, I can't really say more.  Perhaps you can make use of merge.
Give types to struct fields, and don't use mutable structs unless necessary.  Without knowing more, I suggest
struct Foo
    bar::Union{String, Nothing}
    baz::Union{String, Nothing}
    qux::Union{String, Nothing}
end
function Foo(;bar=nothing, baz=nothing, qux=nothing) 
    return Foo(convert(Union{String, Nothing}, bar),
               convert(Union{String, Nothing}, baz),
               convert(Union{String, Nothing}, qux))
end

which also takes care of converting the SubString from the regex match, in case this is relevant.