Using a positive lookbehind, the individual regexes match their respective strings. When combined, they don't. When one is changed by removing a positive lookbehind it matches. I don't understand why and would like to know so that I can fix it because I don't want the match unconsumed.
value = / # match a digit or something wrapped in quotes
(?<value>
\d+ # Match a digit
| # or
(?: # Match something wrapped in double quotes
(?<=") # <- this is the point of contention
[^"]+ # captures anything not a "
(?=")
)
| # or
(?: # Match something wrapped in single quotes
(?<=') # <- or this one
[^']+ # captures anything not a '
(?=')
)
)
/x
value.match %q!'filename.rb'!
# => #<MatchData "filename.rb" value:"filename.rb">
value.match %q!"filename.rb"!
# => #<MatchData "filename.rb" value:"filename.rb">
value.match %q!66!
# => #<MatchData "66" value:"66">
So it matches any digit or anything wrapped in matching quotes.
long_option = /
(?<long_option>
(?<!
(?:\-\-no\-) # don't match --no-long
|
(?:\-\-\-) # don't match ---long
)
(?<=\-\-) # it must begin with --
(?<key_name>
[a-zA-Z]\w+ # capture the key name
)
\b
(?!
\- # make sure it's not part of a longer key
)
)
/x
long_option.match "--long"
# => #<MatchData "long" long_option:"long" key_name:"long">
long_option.match "---long"
# => nil
long_option.match "--long-"
# => nil
long_option.match "--no-long"
# => nil
This also matches nicely.
Now combined, the problems begin:
/#{long_option} #{value}/.match "--long 'filename.rb'"
# => nil
but if value
is redefined without the positive lookbehind for the first quote, it matches:
value2 = /
(?<value>
\d+
|
(?:
" # <- no positive lookbehind
[^"]+
(?=")
)
|
(?:
' # <- for single quote too
[^']+
(?=')
)
)
/x
/#{long_option} #{value2}/.match "--long 'filename.rb'"
# => #<MatchData
"long 'filename.rb"
long_option:"long"
key_name:"long"
value:"'filename.rb">
I've tried combining the long_option
with simpler matches and it works, so I'm inclined to think that it is not an obvious source of the problem, hence my question, e.g.
/#{long_option} abc/.match "--long abc"
# => #<MatchData "long abc" long_option:"long" key_name:"long">
I've gone through the match in my head, and trial and error with slightly different patterns and I'm really stuck. Any help or insight would be much appreciated.
Ruby version is 1.9.