0

肯定的な後読みを使用すると、個々の正規表現がそれぞれの文字列に一致します。組み合わせると、そうではありません。正の後読みを削除して変更すると、一致します。理由がわかりません。マッチを消費しないままにしたくないので、修正できるように知りたいです。

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 です。

4

1 に答える 1

0

/#{long_option} #{value}/valueは、意図したように二重引用符または単一引用符で囲まれた文字列と一致しません。これは、前の文字が二重引用符または単一引用符である場合に一致が成功するの先頭に正の後読みが表示されるためです。しかし では/#{long_option} #{value}/、直前の文字valueはスペースであり、スペース文字は同時に二重引用符または単一引用符になることはできないため、その代替一致は決して成功しません。

于 2013-04-14T15:50:06.580 に答える