my $string = "var1=100 var2=90 var5=hello var3=\"a, b, c\" var7=test var3=hello";
while($string =~ /(?:^|\s+)(\S+)\s*=\s*("[^"]*"|\S*)/g) {
print "<$1> => <$2>\n";
}
Prints:
<var1> => <100>
<var2> => <90>
<var5> => <hello>
<var3> => <"a, b, c">
<var7> => <test>
<var3> => <hello>
Explanation:
Last piece first: the g
flag at the end means that you can apply the regex to the string multiple times. The second time it will continue matching where the last match ended in the string.
Now for the regex: (?:^|\s+)
matches either the beginning of the string or a group of one or more spaces. This is needed so when the regex is applied next time, we will skip the spaces between the key/value pairs. The ?:
means that the parentheses content won’t be captured as group (we don’t need the spaces, only key and value). \S+
matches the variable name. Then we skip any amount of spaces and an equal sign in between. Finally, ("[^"]*"|\S*)/
matches either two quotes with any amount of characters in between, or any amount of non-space characters for the value. Note that the quote matching is pretty fragile and won’t handle escpaped quotes properly, e.g. "\"quoted\""
would result in "\"
.
EDIT:
Since you really want to get the whole assignment, and not the single keys/values, here’s a one-liner that extracts those:
my @list = $string =~ /(?:^|\s+)((?:\S+)\s*=\s*(?:"[^"]*"|\S*))/g;