text = 'http://www.site.info www.escola.ninja.br google.com.ag'
表达:(http:\/\/)?((www\.)?\w+\.\w{2,}(\.\w{2,})?)
在Javascript中,此表达式有效,返回:
["http://www.site.info", "www.escola.ninja.br", "google.com.ag"]
为什么它不在红宝石中工作?
例如:
p text.match(/(http:\/\/)?(www\.)?\w+\.\w{2,}(\.\w{2})?/)
#<MatchData "http://www.site.info" 1:"http://" 2:"www." 3:nil>
p text.scan(/(http:\/\/)?(www\.)?\w+\.\w{2,}(\.\w{2})?/)
[["http://", "www.", nil], [nil, "www.", ".br"], [nil, nil, ".ag"]]
如何返回以下数组呢?
["http://www.site.info", "www.escola.ninja.br", "google.com.ag"]
原因是JS中的str.match(/regex/g)
没有保留捕获的子串,请参阅MDN String#match()
reference:
如果正则表达式包含
g
标志,则该方法返回包含所有匹配的子字符串而不是匹配对象的Array
。捕获的组不会被退回。
在Ruby中,您必须修改模式以删除冗余捕获组并将捕获组转换为非捕获组(即,用(
替换未转义的(?:
),否则,只有捕获的子字符串将通过String#scan
方法输出:
如果模式不包含组,则每个单独的结果由匹配的字符串$&组成。如果模式包含组,则每个单独的结果本身就是一个包含每个组一个条目的数组。
使用
text = 'http://www.site.info www.escola.ninja.br google.com.ag'
puts text.scan(/(?:http:\/\/)?(?:www\.)?\w+\.\w{2,}(?:\.\w{2,})?/)
demo的输出:
http://www.site.info
www.escola.ninja.br
google.com.ag
如果模式包含组,则每个单独的结果本身就是一个包含每个组一个条目的数组。
因此,您可以通过将(...)
转换为(?:...)
来简单地修改表达式以使组无法捕获,从而产生以下表达式
text.scan(/(?:http:\/\/)?(?:(?:www\.)?\w+\.\w{2,}(?:\.\w{2,})?)/)
# => ["http://www.site.info", "www.escola.ninja.br", "google.com.ag"]