给定这个输入文件,存储为“test.txt”:
test
test
test
testing
test
还有这个示例代码:
def remove_line(line_to_remove)
File.foreach("test.txt").with_index do |line, line_num|
line.gsub!(/[\r\n]+$/, '')
if line == line_to_remove
puts "removed successfully"
else
puts line
end
end
end
可以成功运行:
remove_line('testing')
并得到这个输出:
test
test
test
removed successfully
test
该函数获取要删除的行的内容,并以“逐行”方式打开文件。这是惯用的 Ruby,应该优先于“slurping”文件,如对此SO question 的接受答案中所述。
一旦我们有了一条线,就需要从它中去除行尾。由于我们不确切知道它将在哪个平台上运行(或者文本文件是在哪个平台上创建的),我们使用正则表达式来查找所有已知的行结束字符('\r\n' 是 Windows,'\n'是 Linux/Unix/Mac OS X,'\r' 是 Mac Classic)。
然后我们检查该行是否与我们要删除的内容匹配。如果匹配,我们从输出中省略它,而是打印它已“成功删除”;否则,我们输出不匹配的行。
这符合最初的设计意图,但是,还有很多事情要做来改进设计并让整体功能更有用。那么为什么不继续这样做呢?
首先,我们将让函数将文件名作为参数。这将从foreach 调用中删除硬编码的"test.txt" 文件名。这将使这种变化发生:
def remove_line(filename, line_to_remove)
File.foreach(filename).with_index do |line, line_num|
line.gsub!(/[\r\n]+$/, '')
if line == line_to_remove
puts "removed successfully"
else
puts line
end
end
end
您可以通过这种方式成功运行它,它会产生完全相同的输出:
remove_line("test.txt", "testing")
接下来,让我们更改输出的发生方式,我们将使用一个块来执行此操作,因为这就是 Ruby 方式。下面是函数在输出块时的样子:
def remove_line(filename, line_to_remove, &block)
proc = block_given? ? block : lambda {|s| puts s }
File.foreach(filename).with_index do |line, line_num|
line.gsub!(/[\r\n]+$/, '')
if line == line_to_remove
proc.call "removed successfully"
else
proc.call line
end
end
end
这是使用可选的块参数构建的,因此您可以像以前的版本一样调用它以使其工作方式完全相同,或者您可以使用显式块调用它并做一些很酷的事情。这个运行它的示例在调用puts 打印该行之前稍微修改了字符串:
remove_line("test.txt", "testing") {|s| puts "#{s} in your pants" }
再加上一点幼稚,你会得到这样的输出:
test in your pants
test in your pants
test in your pants
removed successfully in your pants
test in your pants
你现在有能力做有趣的事情,从其他有趣的事情开始。明智地使用它并继续使用 Ruby 方式。