简体   繁体   English

Ruby:在模式之后/之前插入一个字符串

[英]Ruby: Insert a string after/before a pattern

I know how to add string(or text) to end of the file as well as beginning of the file, but could not google out the way to insert string (with a variable) after/before a pattern. 我知道如何将字符串(或文本)添加到文件的末尾以及文件的开头,但是无法用谷歌搜索出在模式之后/之前插入字符串(带有变量)的方法。

For example, 例如,

root@vikas:~# cat /etc/resolv.conf
search reachvikas.com
nameserver 192.168.1.27
root@vikas:~#

Now, I want to add another nameserver like below. 现在,我想添加另一个名称服务器,如下所示。

root@vikas:~# cat /etc/resolv.conf
search reachvikas.com
nameserver 192.168.181.2
nameserver 192.168.1.27
root@vikas:~#

I can do this with sed easily, but just looking a way out with Ruby. 我可以很容易地用sed做到这一点,但只是想用Ruby寻找出路。

Update : I have written below code, but this replaces the last line does not adds one. 更新 :我已经写了下面的代码,但这代替了最后一行,没有添加一行。 I guess tweaking file.seek would help me, but not sure how. 我想调整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 

Here's a Ruby "one-liner" that does what I think you're trying to do. 这是Ruby的“单行代码”,它可以完成我认为您要尝试执行的操作。 I created a resolv.conf file matching your first file contents. 我创建了一个与您的第一个文件内容匹配的resolv.conf文件。 Then the following Ruby "one-liner", which I broke into several lines for readability, searches for a line that begins with "nameserver" and inserts an arbitrary list of new namservers with IPs you define. 然后,为便于阅读,我将以下Ruby“单线”分为几行,搜索了以“ nameserver”开头的行,并插入了一个由您定义的IP组成的新namserver的任意列表。

$ 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

If you truly want it as a one-liner, you have to add semicolons where line breaks are needed: 如果您确实希望将其作为单行,则必须在需要换行的地方添加分号:

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

The -i.$SECONDS flag tells the Ruby interpreter to modify your input file in-place and to save the original version with a filename extension of $SECONDS , which is the number of seconds your terminal session has been alive. -i.$SECONDS标志告诉Ruby解释器就地修改您的输入文件,并使用$SECONDS扩展名保存原始版本,该扩展名是您的终端会话存活的秒数。 That makes it very unlikely you will permanently clobber a good file with bad code. 这使得您极不可能永久性地用错误的代码破坏好文件。 The backup copies are there if you need them. 如果需要,则有备份副本。 You just have to clean up afterwards. 之后您只需要清理即可。

EDIT: Here's a short script that inserts rows into an existing file. 编辑:这是将行插入到现有文件中的简短脚本。 Note that this does not save multiple copies of the input file like the one-liner does. 请注意,这不会像单线存储那样保存输入文件的多个副本。 This script reads an input file (resolv.conf), saves modified output to a temp file, then renames that temp file, replacing the original file. 该脚本读取输入文件(resolv.conf),将修改后的输出保存到临时文件,然后重命名该临时文件,替换原始文件。 You would run this in the terminal like this $ ./script.rb resolv.conf 您将在$ ./script.rb resolv.conf这样的终端中运行此命令

Script: 脚本:

#! /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

See the Ruby documentation for the Tempfile class for an explanation of the begin... ensure... end usage and the explicit close on the Tempfile object. 请参阅Ruby文档中的Tempfile类,以了解begin... ensure... end sure begin... ensure... end用法以及对Tempfile对象的显式close

Many thanks Jamin. 非常感谢Jamin。 I have slightly modified your code to suit my future needs as well, like if someone wants to add a block of lines with spaces before a keyword/pattern. 我也略微修改了您的代码以适应我的未来需求,例如,如果有人想在关键字/模式之前添加一行空格。 This is what I have come up with. 这就是我想出的。 May be this helps someone. 也许这可以帮助某人。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM