如何让 gsub 处理多个模式和替换

How to have gsub handle multiple patterns and replacements

不久前,我在 PHP 中创建了一个函数,用于 "twitterize" 通过 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 for gsub 并探索了他们提供的一些示例之后,我仍然找不到解决我的问题的方法:How can I have gsub handle multiple patterns并一次更换多个?

好吧,正如您可以从文档中读到的那样,gsub 不会 一次处理多个模式和替换。这就是导致错误的原因,否则非常明确(您可以将其读作 "give me a String, not an Array!!1")。

你可以这样写:

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

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

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

text.gsub(matching_pattern,replacement_text)

你需要做这样的事情:

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

依此类推,其中模式 1 是您的匹配模式之一,replacement 是您想要的替换文本。