如何在ruby中用regex和.sub覆盖txt文件中的行的一部分

我在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/装置:在线路的不属于任何端数量的字符abel",空间,结肠或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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章