肯定的な後読みを使用すると、個々の正規表現がそれぞれの文字列に一致します。組み合わせると、そうではありません。正の後読みを削除して変更すると、一致します。理由がわかりません。マッチを消費しないままにしたくないので、修正できるように知りたいです。
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">
したがって、一致する引用符で囲まれた任意の数字または何かに一致します。
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
これも見事にマッチ。
組み合わせると、問題が始まります。
/#{long_option} #{value}/.match "--long 'filename.rb'"
# => nil
しかしvalue
、最初の引用符の肯定的な後読みなしで が再定義された場合、次のように一致します。
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">
をより単純なマッチと組み合わせてみましたが、うまくいくので、それが問題の明らかなlong_option
原因ではないと考える傾向があります。したがって、私の質問です。
/#{long_option} abc/.match "--long abc"
# => #<MatchData "long abc" long_option:"long" key_name:"long">
頭の中で試合を見て、少し違うパターンで試行錯誤して、本当に行き詰まりました。どんな助けや洞察も大歓迎です。
Ruby のバージョンは 1.9 です。