Matching attributes list with or without quotes
I'm trying to match a list of a开发者_运维问答ttributes that may have quotes around their value, something like this:
aaa=bbb ccc="ddd" eee=fff
What I want to get is a list of key/value without the quotes.
'aaa' => 'bbb', 'ccc' => 'ddd', 'eee' => 'fff'
The code (ruby) looks like this now :
attrs = {}
str.scan(/(\w+)=(".*?"|\S+)/).each do |k,v|
attrs[k] = v.sub(/^"(.*)"$/, '\1')
end
I don't know if I can get rid of the quotes by just using the regex.
Any idea ? Thanks !
Try using the pipe for the possible attribue patterns, which is either EQUALS, QUOTE, NO-QUOTE, QUOTE
, or EQUALS, NO-WHITESPACE
.
str.scan(/(\w+)=("[^"]+"|\S+)/).each do |k, v|
puts "#{k}=#{v}"
end
Tested.
EDIT | Hmm, ok, I give up on a 'pure' regex solution (that will allow whitespace inside the quotes anyway). But you can do this:
attrs = {}
str.scan(/(\w+)=(?:(\w+)|"([^"]+)")/).each do |key, v_word, v_quot|
attrs[key] = v_word || v_quot
end
The key here is to capture the two alternatives and take advantage of the fact that whichever one wasn't matched will be nil.
If you want to allow whitespace around the =
just add a \s*
on either side of it.
I was able to get rid of the quotes in the regex, but only if I matched the quotes as well.
s = "aaa=bbb ccc=\"ddd\" eee=fff"
s.scan(/([^=]*)=(["]*)([^" ]*)(["]*)[ ]*/).each {|k, _, v, _ | puts "key=#{k} value=#{v}" }
Output is:
key=aaa value=bbb
key=ccc value=ddd
key=eee value=fff
(Match not =)=(Match 0 or more ")(Match not " or space)(Match 0 or more ")zero or more spaces Then just ignore the quote matches in the processing.
I tried a number of combinations with OR's but could not get the operator precedence and matching to work correctly.
I don't know ruby, but maybe something like ([^ =]*)="?((?<=")[^"]*|[^ ]*)"?
works?
精彩评论