Ruby:如何在文件中替换文本?

5
以下代码是xml文件中的一行:

<appId>455360226</appId>

我该如何使用Ruby替换2个标签之间的数字为另一个数字?
4个回答

15

没有办法一步修改文件内容(至少我不知道有这种方法,因为这样会改变文件的大小)。 你需要读取文件,将修改后的文本存储在另一个文件中。

replace="100"
infile = "xmlfile_in"
outfile = "xmlfile_out"
File.open(outfile, 'w') do |out|
  out << File.open(infile).read.gsub(/<appId>\d+<\/appId>/, "<appId>#{replace}</appId>")
end  

或者您可以将文件内容读取到内存中,然后用修改后的内容覆盖文件:

replace="100"
filename = "xmlfile_in"
outdata = File.read(filename).gsub(/<appId>\d+<\/appId>/, "<appId>#{replace}</appId>")

File.open(filename, 'w') do |out|
  out << outdata
end  

(希望它能够运行,代码未经测试)


嘿,如果新数据比旧数据短,那么旧数据的末尾仍将留在您的文件中,导致文件损坏。 - medmonds
@medmonds 不行。我的解决方案重写了整个文件。你描述的问题就是我写“至少我不知道”的原因,当文件大小发生改变时。如果文件大小改变,那么文件就会损坏。这就是为什么没有一步解决方案的原因。 - knut

6
您可以像以下这样一行完成它:
IO.write(filepath, File.open(filepath) {|f| f.read.gsub(//<appId>\d+<\/appId>/, "<appId>42</appId>"/)})

IO.write 默认情况下会截断给定的文件,因此如果您先读取文本,执行正则表达式 String.gsub 并使用块模式的 File.open 返回结果字符串,它将一举替换文件内容。

我喜欢这种写法,但当然也可以分多行写:

IO.write(filepath, File.open(filepath) do |f|
    f.read.gsub(//<appId>\d+<\/appId>/, "<appId>42</appId>"/)
  end
)

2
replace="100"
File.open("xmlfile").each do |line|
  if line[/<appId>/ ]
     line.sub!(/<appId>\d+<\/appId>/, "<appId>#{replace}</appId>")
  end
  puts line
end

这看起来在irb中可以正常工作,但如果我打开实际文件,它似乎没有任何改变。这是全部的代码吗?还是我需要保存什么东西? - thisiscrazy4
当您执行脚本时,请使用重定向运算符>将其保存到另一个文件中。 - ghostdog74

1

正确的方法是使用XML解析工具,例如XmlSimple

你在问题标签中打了regex的标签。如果你真的必须使用正则表达式,则

s = "Blah blah <appId>455360226</appId> blah"
s.sub(/<appId>\d+<\/appId>/, "<appId>42</appId>")

这是一种你可以做但不应该的事情的例子。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接