Ruby只用另一个字符串替换完全匹配的字符串

时间:2013-04-11 23:05:39

标签: ruby-on-rails ruby

如何解决以下问题?

我有一个html字符串,如下所示:

<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>

现在我只想替换

"aaa" 

"<div class='special'>aaa</div>"

替换后的新字符串:

<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>

所以我想要一个通用的替换器,它只替换一个完全匹配的字符串。 “aaa”就是一个例子。它也可能是“bb”或“两个单词”(=&gt;两个单词,所以text.split在我看来不起作用)。

有人想过这样一个动态的查找,匹配和替换吗?

我已经尝试过如下:

items = ["aaa", "a", "aa", "aa b", "c"]
text = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
words = text.split => ["<p>aaa,", "b", "aa", "aaaaa?<br/>Next", "possible", "text", "b", "bb", "aa", "b.</p>"]
new_words = []

words.each do |w|
   items.each do |item|
     if w == item
       w = '<div class="special">#{item}</div>'
     end
   end
  new_words << w
end
text = new_words.join(" ")

结果:

"<p>aaa, b <div class='special'>aa</div> aaaaa?<br/>Next possible text b bb <div class='special'>aa</div> b.</p>"

但它应该是:

"<p><div class='special'>aaa</div>, b <div class='special'>aa</div> aaaaa?<br/>Next possible text b bb <div class='special'>aa b</div>.</p>"

我最大的问题是:

  • 特殊字符,例如“,。?()%€”字符串末尾的字符 =&GT; “aaa,”来自示例
  • 具有相同部分的子串= =比如“aaa”和“aa”
  • 两个单词作为一个项目=&gt;比如示例中的“aa b”

有人想解决我的问题吗?

编辑:某些东西只是我替换的占位符..我真正的替代品也可能是:

%Q( <dfn title="#{strip_tags item.text}">#{item.name}</dfn> )

item.text可以是一切=&gt;也可以包含“aaa” item.name例如是“aaa”

因此,多个gsub也会替换已经替换的内容。

4 个答案:

答案 0 :(得分:2)

您正在寻找String#sub(不是gsub

s = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
# => "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
match = "aaa"
# => "aaa"
replacement = "<div class='special'>aaa</div>"
# => "<div class='special'>aaa</div>"
s.sub match, replacement
# => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
"<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" == _
# => true

答案 1 :(得分:2)

目前尚不清楚是否存在aaa或多个实例,以及是否要将它们全部替换为第一个实例。

这将取代第一个:

text = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
text.sub(/\b(aaa)\b/, %q"<div class='special'>\1</div>")
=> "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"

这将取代所有出现次数:

text = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" * 2
=> "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p><p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"

text.gsub(/\b(aaa)\b/, %q"<div class='special'>\1</div>")
=> "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p><p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"

您可以将"aaa"放入变量并通过将该目标插入到模式中来找到它:

target = 'aaa'
text.gsub(/\b(#{ target })\b/, %q"<div class='special'>\1</div>")
=> "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p><p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"

正则表达式具有\b(分词)标记,可以轻松定义单词或子字符串匹配。您也可以用多个单词替换"aaa"

答案 2 :(得分:1)

我会使用正则表达式,Rubular是学习和测试表达式的好地方。有关如何使用gsub的更多信息,请查看Jayfields Blog post。这可能不适合您遇到此问题的所有用例,因此您可能需要对其进行修改。

    str.gsub /^<p>a{3}/, "<div class='special'>aaa</div>"


   What this says is starting at the beginning of the string (^) 
   find <p> and 3 assurances of the letter a.

答案 3 :(得分:-1)

这是您想要的替代方法(当然使用gsub):

def replacer(orig,pattern,replace)
  orig.gsub(/#{pattern}(\s|\.|,)/,replace+'\1').to_s
end

2.0.0dev :001 > def replacer(orig,pattern,replace)
2.0.0dev :002?>     orig.gsub(/#{pattern}(\s|\.|,)/,replace+'\1').to_s
2.0.0dev :003?>   end
 => nil 
2.0.0dev :004 >  replacer("<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>", "aaa", "<div class='special'>aaa</div>")
 => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"