Ruby中正则表达式的奇怪行为
在我的一个项目中,应用程序必须检查给定页面中是否存在指向给定URL的链接。今天,一个用户报告了一个错误。这是应用程序未检测到的链接:Ruby中正则表达式的奇怪行为,ruby,regex,Ruby,Regex,在我的一个项目中,应用程序必须检查给定页面中是否存在指向给定URL的链接。今天,一个用户报告了一个错误。这是应用程序未检测到的链接: <a\nhref="http://hello.com"... 它为什么坏了 在Ruby中(与大多数正则表达式实现一样),匹配除换行符以外的任何字符,除非您打开“多行”模式: 作为缔约国: 以下元字符的行为也类似于字符类: /./-除换行符以外的任何字符。 //m-任何字符(m修饰符启用多行模式) 当您的代码显式地使用\n时,所有功能都很好,但当您将其切
<a\nhref="http://hello.com"...
它为什么坏了
在Ruby中(与大多数正则表达式实现一样),
匹配除换行符以外的任何字符,除非您打开“多行”模式:
作为缔约国:
以下元字符的行为也类似于字符类:
/./
-除换行符以外的任何字符。
//m
-任何字符(m修饰符启用多行模式)
当您的代码显式地使用\n
时,所有功能都很好,但当您将其切换为仅*
时,它无法与\n
匹配,因此无法继续匹配href
把它修好
与其使用正则表达式解析和使用HTML,不如使用:
有了它,您的代码可以通过以下方式可靠地处理HTML:
- 等号前后的空格
- href之前显示的其他属性
- 用
“
或”
- 混合资本
- 看起来像链接但不是链接的内容(例如,在注释或脚本块中)
它为什么会坏
在Ruby中(与大多数正则表达式实现一样),
匹配除换行符以外的任何字符,除非您打开“多行”模式:
作为缔约国:
以下元字符的行为也类似于字符类:
/./
-除换行符以外的任何字符。
//m
-任何字符(m修饰符启用多行模式)
当您的代码显式地使用\n
时,所有功能都很好,但当您将其切换为仅*
时,它无法与\n
匹配,因此无法继续匹配href
把它修好
与其使用正则表达式解析和使用HTML,不如使用:
有了它,您的代码可以通过以下方式可靠地处理HTML:
- 等号前后的空格
- href之前显示的其他属性
- 用
“
或”
- 混合资本
- 看起来像链接但不是链接的内容(例如,在注释或脚本块中)
默认情况下,ruby中的regexp与换行符不匹配,必须添加
m
修饰符:
/pat/m - Treat a newline as a character matched by .
请查看选项部分:
默认情况下,ruby中的regexp与换行符不匹配,必须添加m
修饰符:
/pat/m - Treat a newline as a character matched by .
请查看选项部分:
不要使用正则表达式来解析HTML文档。@KARASZIIstván:这是一个正则表达式实际上(可能)可以使用的场合。不明智,但不会因为使用正则表达式检查文档中是否存在链接而消耗您的精力。@Li aungYip,除非,您知道,它在HTML注释中。不要使用正则表达式解析HTML文档。@KARASZIIstván:这是一个正则表达式实际上(可能)正常的情况。不明智,但不会因为使用正则表达式检查文档中是否存在链接而消耗你的精力。@Li aungYip,除非,你知道,它在HTML注释中。是的,我可能应该使用Nokogiri。但这是一个经典:你从一个非常简单的解析器开始,它开始变得越来越强大,直到Nokogiri几乎成为强制性的。@Christian-无论解析看起来多么简单,只要你手里拿着xml或html,你就可以从Nokogiri中拔出它,而不需要太多这样的经验。对于regexp来说,它总是变得太复杂了。是的,我可能应该使用Nokogiri。但这是一个经典:你从一个非常简单的解析器开始,它开始变得越来越强大,直到Nokogiri几乎成为强制性的。@Christian-无论解析看起来多么简单,只要你手里拿着xml或html,你就可以从Nokogiri中拔出它,而不需要太多这样的经验。对于regexp来说,它总是变得太复杂。默认情况下,只有点元字符(
)与换行符不匹配。如果正则表达式中没有点,则不需要m
标志。默认情况下,只有点元字符(
)与换行符不匹配。如果正则表达式中没有点,就不需要m
标志。
irb(main):003:0> "foo\nbar"[/.+/]
#=> "foo"
irb(main):004:0> "foo\nbar"[/.+/m]
#=> "foo\nbar"
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"]')
/pat/m - Treat a newline as a character matched by .