替换ruby字符串中的行

时间:2011-11-23 12:23:31

标签: ruby

我正在尝试使用each_line方法遍历包含许多行的Ruby字符串,但我也想更改它们。我正在使用以下代码,但它似乎不起作用:

string.each_line{|line| line=change_line(line)}

我想,Ruby正在发送我的行的副本而不是行本身,但不幸的是没有方法each_line!。我也试过gsub!方法,使用/^.*$/来检测每一行,但它似乎只调用了change_line方法并用它替换了所有行。任何想法如何做到这一点? 在此先感谢:)

5 个答案:

答案 0 :(得分:4)

@azlisum:您没有存储连接的结果。使用:

output = string.lines.map{|line|change_line(line)}.join

比较四种在字符串中逐行处理的方法:

# Inject method (proposed by @steenslang)
output = string.each_line.inject(""){|s, line| s << change_line(line)}

# Join method (proposed by @Lars Haugseth)
output = string.lines.map{|line|change_line(line)}.join

# REGEX method (proposed by @olistik)
output = string.gsub!(/^(.*)$/) {|line| change_line(line)}

# String concatenation += method (proposed by @Erik Hinton)
output = "" 
string.each_line{|line| output += change_line(line)}                   

Benchmark的时间安排:

                   user     system      total        real
Inject Time:   7.920000   0.010000   7.930000 (  7.920128)
Join Time:     7.150000   0.010000   7.160000 (  7.155957)
REGEX Time:   11.660000   0.010000  11.670000 ( 11.661059)
+= Time:       7.080000   0.010000   7.090000 (  7.076423)

正如@steenslag指出的那样,'s + = a'将生成new string for each concatenation,因此通常不是最佳选择。

因此,考虑到时间,最好的选择是:

output = string.lines.map{|line|change_line(line)}.join

此外,这是更清洁的选择恕我直言。

注意:
Using Benchmark
Ruby-Doc: Benchmark

答案 1 :(得分:3)

您应该尝试使用空白字符串开始,每个字符串穿过字符串,然后将结果推送到空白字符串。

output = "" 
string.each_line{|line| output += change_line(line)}

在您的原始示例中,您是对的。你的变化正在发生,但他们并没有在任何地方受到伤害。 Ruby中的Each默认情况下不会改变任何内容。

答案 2 :(得分:1)

你可以使用gsub!将块传递给它:

string.gsub!(/^(.*)$/) {|line| change_line(line)}

来源:String#gsub!

答案 3 :(得分:1)

String#each_line用于读取字符串中的行,而不是写入它们。您可以使用它来获得您想要的结果:

changed_string = ""
string.each_line{ |line| changed_string += change_line(line) }

答案 4 :(得分:0)

如果你没有给each_line一个块,你将获得一个具有inject方法的枚举器。

str = <<HERE
smestring dsfg
line 2
HERE

res = str.each_line.inject(""){|m,line|m << line.upcase}