为什么正则表达式适用于javascript,但不能在ruby中工作?

时间:2017-12-20 21:21:47

标签: ruby regex

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. 使用匹配方法:

    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"]]
    
  3. 如何返回以下数组?

    ["http://www.site.info", "www.escola.ninja.br", "google.com.ag"]
    

2 个答案:

答案 0 :(得分: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"]

答案 1 :(得分:3)

原因是JS中的str.match(/regex/g)没有保留捕获的子字符串,请参阅MDN String#match() reference

  

如果正则表达式包含g标志,则该方法返回包含所有匹配的子字符串而不是匹配对象的Array。捕获的组不会被退回。

在Ruby中,您必须修改模式以删除冗余捕获组并将捕获组转换为非捕获组(即,将非转义(替换为(?:),否则只有捕获的子串将通过String#scan方法输出:

  

如果模式不包含任何组,则每个结果都由匹配的字符串$&amp;组成。 如果模式包含组,则每个单独的结果本身就是一个数组,每个组包含一个条目。

使用

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