Ruby:插入一个字符串after/before一个模式
Ruby: Insert a string after/before a pattern
我知道如何在文件末尾和文件开头添加字符串(或文本),但无法google插入字符串(带变量)after/before一个模式。
例如,
root@vikas:~# cat /etc/resolv.conf
search reachvikas.com
nameserver 192.168.1.27
root@vikas:~#
现在,我想添加另一个名称服务器,如下所示。
root@vikas:~# cat /etc/resolv.conf
search reachvikas.com
nameserver 192.168.181.2
nameserver 192.168.1.27
root@vikas:~#
我可以用 sed 轻松做到这一点,但只是想用 Ruby 寻找出路。
更新: 我已经写了下面的代码,但是这个替换了最后一行并没有添加一个。我想调整 file.seek 会对我有所帮助,但不确定如何。
File.open('/etc/resolv.conf', 'r+') do |file|
count = Integer(0)
file.each do |line|
#puts count
if count == 1
#puts count.to_i
file.seek(-1, IO::SEEK_CUR)
file.puts("\nnameserver 192.168.181.2")
end
count += 1
end
end
这是一个 Ruby "one-liner",我认为您正在尝试这样做。我创建了一个与您的第一个文件内容匹配的 resolv.conf
文件。然后下面的 Ruby "one-liner",为了便于阅读,我将其分成几行,搜索以 "nameserver" 开头的行,并插入一个包含您定义的 IP 的任意新 namservers 列表。
$ cat resolv.conf
search reachvikas.com
nameserver 192.168.1.27
$ ruby -wnl -i.$SECONDS -e '
BEGIN { server_ips = %w(
ip1
ip2
ip3
) }
if $_.start_with?("nameserver")
server_ips.each{ |ip| puts "nameserver #{ip}"; }
end
puts $_
' resolv.conf
$ ls resolv.conf*
resolv.conf resolv.conf.27729
$ cat resolv.conf
search reachvikas.com
nameserver ip1
nameserver ip2
nameserver ip3
nameserver 192.168.1.27
$ cat resolv.conf.27729
search reachvikas.com
nameserver 192.168.1.27
如果你真的想把它作为一行,你必须在需要换行的地方添加分号:
ruby -wnl -i.$SECONDS -e 'BEGIN { server_ips = %w(ip1 ip2 ip3); }; if $_.start_with?("nameserver") ; server_ips.each{|ip| puts "nameserver #{ip}";}; end; puts $_;' resolv.conf
-i.$SECONDS
标志告诉 Ruby 解释器就地修改您的输入文件,并使用 $SECONDS
的文件扩展名保存原始版本,这是seconds 你的终端会话一直存在。这使得你不太可能用错误的代码永久破坏一个好的文件。如果您需要,备份副本就在那里。你只需要事后清理即可。
编辑: 这是一个将行插入现有文件的简短脚本。请注意,这不会像单行文件那样保存输入文件的多个副本。此脚本读取输入文件 (resolv.conf),将修改后的输出保存到临时文件,然后重命名该临时文件,替换原始文件。你会在终端中 运行 这样 $ ./script.rb resolv.conf
脚本:
#! /usr/bin/env ruby
require 'tempfile'
require 'fileutils'
server_ips = %w(
ip1
ip2
ip3
)
input_file = ARGV[0]
temp_file = Tempfile.new("#{input_file}.temp")
modified = false
begin
File.open(input_file, 'r') do |file|
file.each_line do |line|
if modified == false && line.start_with?('nameserver')
server_ips.each do |ip|
temp_file.puts "nameserver #{ip}"
end
modified = true
end
temp_file.print line
end
end
temp_file.close
FileUtils.mv(temp_file.path, input_file)
ensure
temp_file.close!
end
有关 Tempfile class 的 Ruby 文档,了解 begin... ensure... end
用法的解释以及 Tempfile 对象上的显式 close
。
非常感谢 Jamin。我也稍微修改了您的代码以满足我未来的需要,就像有人想在 keyword/pattern 之前添加一段带空格的行一样。这就是我想出的。可能这对某人有帮助。
txt_to_insert = %q(nameserver 192.168.181.2
nameserver 8.8.8.8)
input_file = "/etc/resolv.conf"
temp_file = Tempfile.new("tmp_file.temp")
modified = false
begin
File.open(input_file, 'r') do |file|
file.each_line do |line|
if modified == false && line.start_with?('nameserver')
temp_file.puts txt_to_insert
modified = true
end
temp_file.print line
end
end
temp_file.close
FileUtils.mv(temp_file.path, input_file)
ensure
temp_file.close!
end
我知道如何在文件末尾和文件开头添加字符串(或文本),但无法google插入字符串(带变量)after/before一个模式。
例如,
root@vikas:~# cat /etc/resolv.conf
search reachvikas.com
nameserver 192.168.1.27
root@vikas:~#
现在,我想添加另一个名称服务器,如下所示。
root@vikas:~# cat /etc/resolv.conf
search reachvikas.com
nameserver 192.168.181.2
nameserver 192.168.1.27
root@vikas:~#
我可以用 sed 轻松做到这一点,但只是想用 Ruby 寻找出路。
更新: 我已经写了下面的代码,但是这个替换了最后一行并没有添加一个。我想调整 file.seek 会对我有所帮助,但不确定如何。
File.open('/etc/resolv.conf', 'r+') do |file|
count = Integer(0)
file.each do |line|
#puts count
if count == 1
#puts count.to_i
file.seek(-1, IO::SEEK_CUR)
file.puts("\nnameserver 192.168.181.2")
end
count += 1
end
end
这是一个 Ruby "one-liner",我认为您正在尝试这样做。我创建了一个与您的第一个文件内容匹配的 resolv.conf
文件。然后下面的 Ruby "one-liner",为了便于阅读,我将其分成几行,搜索以 "nameserver" 开头的行,并插入一个包含您定义的 IP 的任意新 namservers 列表。
$ cat resolv.conf
search reachvikas.com
nameserver 192.168.1.27
$ ruby -wnl -i.$SECONDS -e '
BEGIN { server_ips = %w(
ip1
ip2
ip3
) }
if $_.start_with?("nameserver")
server_ips.each{ |ip| puts "nameserver #{ip}"; }
end
puts $_
' resolv.conf
$ ls resolv.conf*
resolv.conf resolv.conf.27729
$ cat resolv.conf
search reachvikas.com
nameserver ip1
nameserver ip2
nameserver ip3
nameserver 192.168.1.27
$ cat resolv.conf.27729
search reachvikas.com
nameserver 192.168.1.27
如果你真的想把它作为一行,你必须在需要换行的地方添加分号:
ruby -wnl -i.$SECONDS -e 'BEGIN { server_ips = %w(ip1 ip2 ip3); }; if $_.start_with?("nameserver") ; server_ips.each{|ip| puts "nameserver #{ip}";}; end; puts $_;' resolv.conf
-i.$SECONDS
标志告诉 Ruby 解释器就地修改您的输入文件,并使用 $SECONDS
的文件扩展名保存原始版本,这是seconds 你的终端会话一直存在。这使得你不太可能用错误的代码永久破坏一个好的文件。如果您需要,备份副本就在那里。你只需要事后清理即可。
编辑: 这是一个将行插入现有文件的简短脚本。请注意,这不会像单行文件那样保存输入文件的多个副本。此脚本读取输入文件 (resolv.conf),将修改后的输出保存到临时文件,然后重命名该临时文件,替换原始文件。你会在终端中 运行 这样 $ ./script.rb resolv.conf
脚本:
#! /usr/bin/env ruby
require 'tempfile'
require 'fileutils'
server_ips = %w(
ip1
ip2
ip3
)
input_file = ARGV[0]
temp_file = Tempfile.new("#{input_file}.temp")
modified = false
begin
File.open(input_file, 'r') do |file|
file.each_line do |line|
if modified == false && line.start_with?('nameserver')
server_ips.each do |ip|
temp_file.puts "nameserver #{ip}"
end
modified = true
end
temp_file.print line
end
end
temp_file.close
FileUtils.mv(temp_file.path, input_file)
ensure
temp_file.close!
end
有关 Tempfile class 的 Ruby 文档,了解 begin... ensure... end
用法的解释以及 Tempfile 对象上的显式 close
。
非常感谢 Jamin。我也稍微修改了您的代码以满足我未来的需要,就像有人想在 keyword/pattern 之前添加一段带空格的行一样。这就是我想出的。可能这对某人有帮助。
txt_to_insert = %q(nameserver 192.168.181.2
nameserver 8.8.8.8)
input_file = "/etc/resolv.conf"
temp_file = Tempfile.new("tmp_file.temp")
modified = false
begin
File.open(input_file, 'r') do |file|
file.each_line do |line|
if modified == false && line.start_with?('nameserver')
temp_file.puts txt_to_insert
modified = true
end
temp_file.print line
end
end
temp_file.close
FileUtils.mv(temp_file.path, input_file)
ensure
temp_file.close!
end