なぜ壊れているのか
Rubyでは(ほとんどの正規表現の実装と同様に)、「マルチライン」モードをオンにしない限り、改行以外の.
すべての文字に一致します。
irb(main):003:0> "foo\nbar"[/.+/]
#=> "foo"
irb(main):004:0> "foo\nbar"[/.+/m]
#=> "foo\nbar"
公式のRuby1.9正規表現ドキュメントには次のように記載されています。
次のメタ文字も文字クラスのように動作
/./
します。-改行を除くすべての文字。
/./m
-任意の文字(m修飾子は複数行モードを有効にします)
コードが明示的にすべてを消費した場合は\n
すべてうまく機能しましたが、コードをに切り替えた場合は、と.*
一致し\n
なかったため、一致し続けることができませんでしたhref
。
それをより良く修正する
正規表現を使用してHTMLを〜解析して消費する代わりに、実際のHTMLパーサーを使用することをお勧めします。
require 'nokogiri' # gem install nokogiri
doc = Nokogiri.HTML( my_html_string )
# Find it using XPath...
first_hello_link = doc.at('//a[starts-with(@href,"http://hello.com")]')
# ...or using CSS
first_hello_link = doc.at('a[href^="http://hello.com"]')
これにより、コードは次の方法でHTMLを堅牢に処理できます。
- 等号の前後のスペース
- hrefの前に表示される追加の属性
"
またはのいずれかで引用'
- 混合キャピタライゼーション
- リンクのように見えるがそうではないもの(コメントやスクリプトブロックなど)