我在txt文件中有以下布局。
[item] label1: comment1 | label2: foo
我有下面的代码。目的是修改文本中现有行的一部分
def replace_info(item, bar)
return "please create a file first" unless File.exist?('site_info.txt')
IO.foreach('site_info.txt','a+') do |line|
if line.include?(item)
#regex should find the data from the whitespace after the colon all the way to the end.
#this should be equivalent to foo
foo_string = line.scan(/[^"label2: "]*\z/)
line.sub(foo_string, bar)
end
end
end
请指教。也许我regrex
已退出,但是.sub
正确的,但我无法覆盖line
。
小问题:您的正则表达式没有按照您的想法做。/[^"label2: "]*\z/
装置:在线路的不属于任何端数量的字符a
,b
,e
,l
,"
,空间,结肠或2
(参见字符类)。并scan
返回一个sub
不能使用的数组。但这并不重要,因为...
小问题:line.sub(foo_string, bar)
什么都不做。它返回一个已更改的字符串,但是您没有将其分配给任何内容,而是将其丢弃。line.sub!(foo_string, bar)
会改变line
自己,但这导致我们...
大问题:您不能只更改读取行并期望它会在文件本身中更改。这就像读一本书,以为您可以写出更好的文字,并期望它能改变这本书。更改文本文件中的行的方法是从一个文件读取并将读取的内容复制到另一个文件。如果您在读取和写入之间更改了界线,则新写入的副本将有所不同。最后,您可以将新文件重命名为旧文件(这将删除旧文件并将其原子替换为新文件)。
编辑:这是一些代码。首先,我不喜欢IO.foreach
自己控制迭代(我IO.foreach
也不喜欢IMO IO#each_line
)。在正则表达式中,我使用了lookbehind来查找标签而不将其包含在匹配中,因此我可以只替换值。\Z
由于类似原因,我将更改为从比赛中排除换行符。您不应该从函数中返回错误消息,这就是异常的原因。我简单include?
地更改为,#start_with?
因为item
当我们不想触发更改时,可能会在行中的其他位置找到您。
class FileNotFoundException < RuntimeError; end
def replace_info(item, bar)
# check if file exists
raise FileNotFoundException unless File.exist?('site_info.txt')
# rewrite the file
File.open('site_info.txt.bak', 'wt') do |w|
File.open('site_info.txt', 'rt') do |r|
r.each_line do |line|
if line.start_with?("[#{item}]")
line.sub!(/(?<=label2: ).*?\Z/, bar)
end
w.write(line)
end
end
end
# replace the old file
File.rename('site_info.txt.bak', 'site_info.txt')
end
replace_info("item", "bar")
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句