0

href タグをその URL に置き換えることになっている次のコード スニペットを見てください。

irb> s='<p><a href="http://localhost/activate/57f7e805827f" style="color:#F19300;font-weight:bold">Click here!</a></p>'
irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
=> "<p></p>"

この正規表現は失敗します (URL が見つかりません)。<次に、正規表現で文字をエスケープすると、機能します。

irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^\<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/57f7e805827f</p>"

1: RubyMine の検査によると、このエスケープは必要ないはずです。これは正しいです?もしそうなら、なぜエスケープも>明らかに必要ではないのですか?

2:その後、同じ IRB セッションで、同じ文字列を使用して、元の正規表現も突然機能します。

irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/57f7e805827f</p>"

これは、再度$1呼び出したときに変数がクリアされていないためですか? gsubもしそうなら、それは意図的な動作ですか、それとも Ruby 正規表現のバグですか?

3:文字列を変更して同じコマンドを再実行すると、変更された文字列に対して 2 回$1呼び出した後にのみ変更されます。gsub

irb> s='<p><a href="http://localhost/activate/xxxxyyy" style="color:#F19300;font-weight:bold">Click here!</a></p>'
=> "<p><a href=\"http://localhost/activate/xxxxyyy\" style=\"color:#F19300;font-weight:bold\">Click here!</a></p>"
irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^\<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/57f7e805827f</p>"
irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^\<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/xxxxyyy</p>"

これは意図的なものですか?もしそうなら、これの背後にあるロジックは何ですか?

4:置換文字として、チュートリアルによっては を使用することを提案する"#{$n}"ものもあれば、 を使用することを提案するものもあり'\n'ます。バックスラッシュのバリアントでは、上記の問題は発生しません。なぜ - 2つの違いは何ですか?

ありがとうございました!

4

1 に答える 1

2

$1最後の一致の最初のキャプチャが含まれます。あなたの例では、マッチングの前に(実際には呼び出される前に)評価されるためgsub、の値$1は固定されてnilいます(まだ何も一致していないため)。したがって、常にの一致の最初のキャプチャを取得します。元の正規表現を変更して、2 回目に期待される結果を取得する必要さえありません。

s='<p><a href="http://localhost/activate/57f7e805827f" style="color:#F19300;font-weight:bold">Click here!</a></p>'

s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
# => "<p></p>"

s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
# => "<p>http://localhost/activate/57f7e805827f</p>"

ブロックを渡すことができますが、これはマッチングgsubに評価されます。

s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/){ $1 }
# => "<p>http://localhost/activate/57f7e805827f</p>"

このように、$1期待どおりに動作します。私は常に名前付きキャプチャを使用するのが好きなので、キャプチャを追加するときに番号を追跡する必要はありません:

s.gsub(/<a href="(?<href>([^ '"]*))"([^>]*)?>([^<]*)<\/a>/){ $~[:href] }
# => "<p>http://localhost/activate/57f7e805827f</p>"
于 2012-10-28T12:54:04.960 に答える