为什么正则表达式适用于javascript,但不适用于ruby?

问题描述 投票:3回答:2
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"]

为什么它不在红宝石中工作?

例如:

  1. 使用Match方法: p text.match(/(http:\/\/)?(www\.)?\w+\.\w{2,}(\.\w{2})?/) #<MatchData "http://www.site.info" 1:"http://" 2:"www." 3:nil>
  2. 使用扫描方法: 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"]
ruby regex
2个回答
3
投票

原因是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

4
投票

因为根据Ruby String#scan method

如果模式包含组,则每个单独的结果本身就是一个包含每个组一个条目的数组。

因此,您可以通过将(...)转换为(?:...)来简单地修改表达式以使组无法捕获,从而产生以下表达式

text.scan(/(?:http:\/\/)?(?:(?:www\.)?\w+\.\w{2,}(?:\.\w{2,})?)/)
# => ["http://www.site.info", "www.escola.ninja.br", "google.com.ag"]
© www.soinside.com 2019 - 2024. All rights reserved.