gsub用于多种模式和多个替换

时间:2015-02-10 03:00:17

标签: ruby-on-rails ruby regex twitter

不久前,我在PHP中创建了一个函数,允许我“推特”通过Twitter的API提取的推文文本。

这就是它的样子:

function twitterize($tweet){
$patterns = array ( "/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/", 
                    "/(?<=^|(?<=[^a-zA-Z0-9-\.]))@([A-Za-z_]+[A-Za-z0-9_]+)/",
                    "/(?<=^|(?<=[^a-zA-Z0-9-\.]))#([A-Za-z_]+[A-Za-z0-9_]+)/");
$replacements = array ("<a href='\\0' target='_blank'>\\0</a>", "<a href='http://twitter.com/\\1' target='_blank'>\\0</a>", "<a href='http://twitter.com/search?q=\\1&src=hash' target='_blank'>\\0</a>");

return preg_replace($patterns, $replacements, $tweet);

}

现在我对Ruby的gsub感到有些困惑,我试过了:

def twitterize(text)
patterns = ["/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/", "/(?<=^|(?<=[^a-zA-Z0-9-\.]))@([A-Za-z_]+[A-Za-z0-9_]+)/", "/(?<=^|(?<=[^a-zA-Z0-9-\.]))#([A-Za-z_]+[A-Za-z0-9_]+)/"]
replacements =  ["<a href='\\0' target='_blank'>\\0</a>",
                "<a href='http://twitter.com/\\1' target='_blank'>\\0</a>",
                "<a href='http://twitter.com/search?q=\\1&src=hash' target='_blank'>\\0</a>"]

return text.gsub(patterns, replacements)
end

这显然不起作用并返回错误:

No implicit conversion of Array into String

在查看了Ruby documentation on gsub并浏览了他们提供的一些示例之后,我仍然无法找到问题的解决方案:让gsub同时处理多个模式和多个替换< /强>

帮助? :)

2 个答案:

答案 0 :(得分:2)

好了,正如您可以从文档中读到的那样,gsub 不会一次处理多个模式和替换。这是导致你的错误的原因,否则就是非常明确的(你可以把它读作&#34;给我一个String,而不是一个数组!! 1&#34;)。

你可以这样写:

def twitterize(text)
  patterns = [/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/, /(?<=^|(?<=[^a-zA-Z0-9-\.]))@([A-Za-z_]+[A-Za-z0-9_]+)/, /(?<=^|(?<=[^a-zA-Z0-9-\.]))#([A-Za-z_]+[A-Za-z0-9_]+)/]
  replacements =  ["<a href='\\0' target='_blank'>\\0</a>",
            "<a href='http://twitter.com/\\1' target='_blank'>\\0</a>",
            "<a href='http://twitter.com/search?q=\\1&src=hash' target='_blank'>\\0</a>"]

  patterns.each_with_index do |pattern, i|
    text.gsub!(pattern, replacements[i])
  end

  text
end

这可以重构为更优雅的rubyish代码,但我认为它可以完成这项工作。

答案 1 :(得分:0)

错误是因为您尝试在 gsub 函数中使用替换数组代替字符串。它的语法是

<强> text.gsub(matching_pattern,replacement_text)

所以你需要在ruby中做这样的事情

 replaced_text = text.gsub(pattern1, replacement1)
 replaced_text = replaced_text.gsub(pattern2, replacement2)

等等。模式1是您的匹配模式之一,替换是您想要的替换文本。

干杯。