从正则表达式中转义匹配的结果

时间:2013-04-09 22:16:44

标签: ruby regex

测试将嵌入式soundcloud-track网址更改为iframe的方法时。我在逃避结果时遇到了一个错误。

有人可以解释为什么在CASE 2中转义+ token +会中断吗?我可以使用结果附加

下面详细介绍了这两种情况。

#ruby --version
# => ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin12.2.1]

案例1

require 'cgi'

class String
  def embedda
    compiled = self
    compiled = soundcloud_replace(compiled)

    return compiled
  end

 private
  def soundcloud_replace(compiled)
    r = /(https?:\/\/(?:www.)?soundcloud.com\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*(?!\/sets(?:\/|$))(?:\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*){1,2}\/?)/i
    compiled.gsub!(r) { |match| soundcloud_player(match) }

    return compiled
  end

  def soundcloud_player(token)
    # return token # => +matched soundcloud url+ in pry
    # puts token   # => +matched soundcloud url+ in pry

    url_encoded_string = CGI::escape(token)

    # puts url_encoded_string # => +escaped matched soundcloud url+

    # "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{token}\"></iframe>"
    # => Correct interpolated string with non-encoded url

    "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{url_encoded_string}\"></iframe>"
    # => Correct interpolated string with encoded url
  end
end

案例2

require 'cgi'

class String
  def embedda
    compiled = self
    compiled = soundcloud_replace(compiled)

    return compiled
  end

 private
  def soundcloud_replace(compiled)
    compiled.gsub!(/(https?:\/\/(?:www.)?soundcloud.com\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*(?!\/sets(?:\/|$))(?:\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*){1,2}\/?)/i, soundcloud_player("\\1"))

    return compiled
  end

  def soundcloud_player(token)
    # return token # => +matched soundcloud url+  in pry
    # puts token   # => /1                        in pry

    url_encoded_string = CGI::escape(token)

    # puts url_encoded_string = CGI::escape(token) # => %5C1  in pry

    # "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{token}\"></iframe>"
    # => Correct interpolated string with non-encoded url

    "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{url_encoded_string}\"></iframe>"
    # => Interpolated string with ...?url=%5C1
  end
end

2 个答案:

答案 0 :(得分:1)

在第二种情况下,在将其提供给gsub之前,您将转义“\ 1”。转义后“url_encoded_string”包含“%5C1”。由于“\ 1”不存在,因此不会插入任何内容。相反,内容将替换为“url_encoded_string”的内容。

尝试以下操作并查看案例2中的区别:

url_encoded_string = token

而不是:

url_encoded_string = CGI::escape(token)

答案 1 :(得分:0)

用于显示问题的更简单版本:

案例1:

require 'cgi'

def soundcloud_player(token)
  url_encoded_string = CGI::escape(token)
  "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{url_encoded_string}\"></iframe>"
end

soundcloud_string = "https://soundcloud.com/theeconomist/money-talks-april-8th-2013"
r = /(https?:\/\/(?:www.)?soundcloud.com\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*(?!\/sets(?:\/|$))(?:\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*){1,2}\/?)/i
soundcloud_string.gsub!(r) { |match| soundcloud_player(match) }
puts soundcloud_string.inspect
# => Correct interpolated string with encoded url:
# "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=https%3A%2F%2Fsoundcloud.com%2Ftheeconomist%2Fmoney-talks-april-8th-2013\"></iframe>"

案例2:

require 'cgi'

def soundcloud_player(token)
  url_encoded_string = CGI::escape(token)
  "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{url_encoded_string}\"></iframe>"
end

soundcloud_string = "https://soundcloud.com/theeconomist/money-talks-april-8th-2013"
soundcloud_string.gsub!(/(https?:\/\/(?:www.)?soundcloud.com\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*(?!\/sets(?:\/|$))(?:\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*){1,2}\/?)/i, soundcloud_player("\\1"))
puts soundcloud_string.inspect
# => Interpolated string with ...?url=%5C1:
# "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=%5C1\"></iframe>"