Ruby中正则表达式的奇怪行为

时间:2012-05-07 15:35:50

标签: ruby regex

在我的一个项目中,应用程序必须检查给定页面中是否存在指向给定URL的链接。今天用户报告了一个错误。这是应用程序未检测到的链接:

  <a\nhref="http://hello.com"...

我试着测试它为什么不起作用,这里出现了奇怪的行为。此正则表达式匹配链接:

/\<a.*\nhref=\"http:\/\/hello.com/

但这不是:

/\<a.*href=\"http:\/\/hello.com/

我猜它与我正在使用的Ruby版本有一些关系(1.9.3),因为Rubular匹配最后一个正则表达式。

2 个答案:

答案 0 :(得分:4)

为什么它被打破

在Ruby中(与大多数正则表达式实现一样).匹配除换行符之外的任何字符 ,除非您打开“多行”模式:

irb(main):003:0> "foo\nbar"[/.+/]
#=> "foo"

irb(main):004:0> "foo\nbar"[/.+/m]
#=> "foo\nbar"

正如official Ruby 1.9 regex documentation所述:

  

以下元字符的行为也类似于字符类:
  /./ - 除换行符之外的任何字符   /./m - 任何字符(m修饰符启用多行模式)

当您明确使用\n的代码时效果很好,但当您将其切换为.*时,它与\n无法匹配,因此无法继续匹配href 1}}。

更好地修复

不使用正则表达式来解析和使用HTML,最好使用a real HTML parser

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
  • 之前出现的其他属性
  • 引用"'
  • 混合资本化
  • 看起来像链接但不是(例如在评论或脚本块中)的内容

答案 1 :(得分:1)

默认情况下,ruby中的正则表达式与换行符不匹配,您必须添加m修饰符:

/pat/m - Treat a newline as a character matched by .

查看选项部分:

http://www.ruby-doc.org/core-1.9.3/Regexp.html