使用Ruby中的“+”文件IO模式替换文件中的一行

4

这里是一位Ruby初学者!

我知道Ruby的File.open方法有一些模式,如r、w、a、r+、w+、a+和补充的b。我完全理解r、w和a模式的用法。但是我似乎无法理解带“+”符号的那些模式的用法。是否可以提供一些链接,其中包括使用示例和说明?

它可以用来读取一行,并在原地通过相等数量的内容进行编辑/替换吗?如果可以,那么如何操作呢?

示例数据文件:a.txt

aaa
bbb
ccc
ddd

Demo.rb

file = File.open "a.txt","r+"
file.each do |line|
  line = line.chomp
  if(line=="bbb")then
  file.puts "big"
  end
end
file.close

我试图将"bbb"替换为"big",但我得到了这个结果:- 在notepad++中

aaa
bbb
big

ddd

在记事本中

aaa
bbb
bigddd

2
可能是differences between ruby file access mode r+ and w+的重复问题。 - Sergio Tulentsev
1
你需要哪些示例?你可以使用r+模式打开文件,然后进行读写操作。请查看文档,它非常全面。 - Sergio Tulentsev
2
我冒昧修改了您的标题,使其看起来不像是重复的。 - Mark Thomas
我在我的回答中包含了你的示例。 - peter
2个回答

11

我从另一个答案中获取了这个文档,所以不是我的,但解决方案是我的

r  Read-only mode. The file pointer is placed at the beginning of the file. This is the default mode. 
r+ Read-write mode. The file pointer will be at the beginning of the file. 
w  Write-only mode. Overwrites the file if the file exists. If the file does not exist, creates a new file for writing. 
w+ Read-write mode. Overwrites the existing file if the file exists. If the file does not exist, creates a new file for reading and writing.
a  Write-only mode. The file pointer is at the end of the file if the file exists. That is, the file is in the append mode. If the file does not exist, it creates a new file for writing. 
a+ Read and write mode. The file pointer is at the end of the file if the file exists. The file opens in the append mode. If the file does not exist, it creates a new file for reading and writing.

编辑:这里是针对您示例的解决方案。大多数情况下,整个字符串会被替换并写回文件,但是也有可能进行'infile'替换而无需重写整个文件。您应该小心地使用与原字符串相同长度的字符串进行替换。

File.open('a.txt', 'r+') do |file|
  file.each_line do |line|
    if (line=~/bbb/)
      file.seek(-line.length-3, IO::SEEK_CUR)
      file.write 'big'
    end
  end
end 

=>
aaa
big
ccc
ddd

这是一种更传统的方式,虽然比大多数其他解决方案更简洁。

File.open(filename = "a.txt", "r+") { |file| file << File.read(filename).gsub(/bbb/,"big") } 

编辑2:我现在意识到这还可以更短

File.write(f = "a.txt", File.read(f).gsub(/bbb/,"big"))

它们(w+,r+)的使用有哪些例子? - Jazz
所以你正在将整个文件读入一个变量,然后执行替换,最后将变量的内容写回文件。我理解得对吗?我在找类似一行内处理的方法。 - Jazz
为什么要复制粘贴已经在每个文档(文件模式)和这里的几个类似答案中的内容呢? - Ernest
看到你的答案因为重复一些文档而被踩是很遗憾的,因为这正是解决问题的关键。OP要求不要替换和重写整个文件,只是其中的一部分,而这正是这个答案所做的。 - peter
1
爵士,因为你可能在某个地方有额外的空格、行或回车字符,无论如何,我只会使用这种方法来处理非常大的文件,以便它们不必被复制,我添加了一个更常见的解决方案,其中文件被完全重写,但没有使用第二个文件。希望这对你足够好。 - peter
显示剩余3条评论

0
所以你正在将整个文件读入变量中,然后执行替换,最后将变量的内容写回文件。我说得对吗?我正在寻找一些内联的东西。
没错,这就是做法。你也可以使用IO#readlines将所有行读入Array,然后处理它们。
而且这个问题已经有答案了:

如何搜索文件文本以查找模式并用给定值替换它

如果你担心性能或内存使用情况,那么请使用正确的工具来完成正确的工作。在*nix(或Windows上的cygwin)上:
sed -i -e "s/bbb/big/g" a.txt

会完全按照你的要求执行。


你会认真安装Cygwin在Windows上进行字符串替换吗?Ruby本身已经足够快并且能够胜任,如果你需要一个外部工具,有很多Windows工具可供选择。 - peter
@peter 我在哪里暗示你需要安装cygwin来完成这个任务?很多人已经有了它。至于Windows工具,可能是真的,鼓励你给出一个例子。 - Ernest
Ernest: 问题是,你怎么在评论开头加上@Ernest?我试过了,但不行。 - peter
Jazz,您有SED,在此查看我的第三条评论,虽然我不建议使用它,但是我的答案中的最后一个解决方案可能是最适合您的。 - peter
Ernest,非常真诚地感谢您的努力!而Peter,在我的Ruby(1.9.3)/bin文件夹中没有sed.exe文件。无论如何,问题已经解决。 - Jazz
显示剩余2条评论

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