2012-03-02 14 views
1

我是一个红宝石初学者,我发现一个问题,我想知道是否有更多的'红宝石方式' 来解决它。如何用Ruby中的str.sub替换多个grep结果?

我的问题是: 我得到一个字符串,像这样:

str = "<div class=\"yui-u first\">\r\n\t\t\t\t\t<h1>Jonathan Doe</h1>\r\n 
\t\t\t\t\t<h2>Web Designer, Director</h2>\r\n\t\t\t\t</div>" 

# now, i want to replace the substring in <h1> </h1> and <h2> and </h2> with 
these two string:"fooo" and "barr". 

这里是我做过什么:

# first, i got the exactly matched substrings of str: 
r = str.scan(/(?<=<h\d>).*?(?=<\/h\d>)/) 
# then, i create a hash table to set the corresponding replace strings 
h = {r[0] => 'fooo', r[1] => 'barr'} 
# finally, using str.gsub to replace those matched strings 
str.gsub!(/(?<=<h\d>).*?(?=<\/h\d>)/, h) 
# or like this 
str.gsub!(/(?<=<h\d>).*?(?=<\/h\d>)/) {|v| h[v]} 

PS:在<h1> </h1><h2> </h2>的字符串是不固定的,所以我有 首先得到这些字符串,以便我可以建立一个哈希表。但我 真的不喜欢上面的代码(因为我写了两行几乎相同), 我认为必须有一个优雅的方式来这样做。我试过这样的事情:

str.gsub!(/(?<=<h\d>).*?(?=<\/h\d>)/) { ['fooo', 'barr'].each {|v| v}} 

但这没有奏效。因为这个块返回['fooo','barr'] EVERYTIME! 如果有办法让这个块(或某物?)一次返回一个元素(第一次返回'fooo',然后在第二次返回'barr'),我的问题就解决了! 谢谢!

+0

为什么你在一个字符串中有HTML?有解析HTML文件吗?如果是这样,最好使用像Nokogiri这样的HTML解析器。 – 2012-03-02 16:39:58

+0

我认为这是一个常见的情况:)它真的没关系,如果这来自一个HTML或其他东西 – sunus 2012-03-02 16:42:57

+0

其实,它很重要。如果这是一个选项,您可以使用HTML解析器节省大量时间和精力。结果会更加强大。 – 2012-03-02 16:46:02

回答

1

尽管你真的没有业务parsing HTML with a regexp,像Nokogiri图书馆可以使这个你可以直接修改DOM显著容易,你正在做的错误是在假定迭代器将每替代,只有执行一次该块将只返回一个值。 each实际上会返回被迭代的对象。

下面就来避免所有的正则表达式疯狂的方式:

require 'rubygems' 
gem 'nokogiri' 
require 'nokogiri' 

str = "<div class=\"yui-u first\">\r\n\t\t\t\t\t<h1>Jonathan Doe</h1>\r\n 
\t\t\t\t\t<h2>Web Designer, Director</h2>\r\n\t\t\t\t</div>" 

html = Nokogiri::HTML(str) 

h1 = html.at_css('h1') 
h1.content = 'foo' 

h2 = html.at_css('h2') 
h2.content = 'bar' 

puts html.to_s 

如果你想要做的多重替换,每个都有不同的价值,简单的办法是刚刚从堆栈撕掉值:

subs = %w[ foo bar baz ] 

string = "x x x" 

string.gsub!(/x/) do |s| 
    subs.shift 
end 

puts string.inspect 
# => "foo bar baz" 

请记住subs在这里消耗。更有效的方法是增加某种索引变量并使用该值,但这是一个微不足道的修改。

+0

哇!真的很喜欢你的答案,一个使用堆栈。我想这就是我一直都在寻找的东西。非常感谢你! – sunus 2012-03-02 16:51:26