Ronald Elciario
Ronald Elciario

Reputation: 1

search and replace a string from a file

I’m trying to create a unix script with this scenario:

My main config file contains this line:

#BEGIN mytest
#END mytest

My input file has:

location /server/ {
                  (proxy config here) 
                 }

I wanted to create a script that will search for #BEGIN mytest and if found add another line which contains my input file, the output will be like:

#BEGIN mytest
location /server/ {
                  (proxy config here) 
                 } 

#END mytest

Upvotes: 0

Views: 37

Answers (2)

aks
aks

Reputation: 2348

The specification is not consistent. You write 'search for "#BEGIN mytest"', but the given output is lacking '#'. I'll assume that '#' is a comment character, and you want the configuration files to have bracketing comment text of #BEGIN mytest and #END mytest. Given that, the following ruby script will do the trick:


#!/usr/bin/env/ruby
# update-cfg-file CFGFILE [NAME FILE] ...
#
# read CFGFILE and look for occurrences of '#BEGIN NAME', and (replace and)
# insert the contents of FILE2 inline into CFGFILE.  all the original text (if
# any) from CFGFILE up to #END NAME' will be replaced by FILE2.
#
# Multiple occurrences of NAME FILE may be given, each unique name being
# associated with the contents of the subsequent FILE.
#
# if there are no occurrences of '#BEGIN NAME' within CFGFILE, no changes are
# made.  If there are changes, the previous copy of CFGFILE is retained as
# CFGFILE.TIMESTAMP, where TIMESTAMP is YYYY-MM-DD.HH.MM.SS

cfgfile_name = ARGV.shift || raise "No CONFIGFILE argument"

def talk msg
  $stderr.puts msg
end

files = {}
while ARGV.size > 0 do
  name = ARGV.shift
  name_file = ARGV.shift
  break if name.empty? || name_file.empty?
  if !File.exist? name_file
    raise "#{name_file} does not exist"
  end
  files[name] = name_file
end

if files.size == 0
  raise "No NAME FILE pairs given"
end

new_cfgfile = cfgfile + '.new'

cfgin = open(cfgfile, 'r')
cfgout = open(new_cfgfile, 'w')

name_re = files.keys.join('|')

changes = false
while line = cfgin.gets do
  cfgout.puts line                              # output the line
  if line =~ /^#\s*BEGIN\s+(#{name_re})\>/      # was it a boundary?
    matched_name = $1
    if files.key?(matched_name)                 # one of our keys?
      talk "Found #{matched_name}"
      while end_line = cfgin.gets do            # skip until the closing boundary
        break if end_line =~ /^#\s*END\s+#{matched_name}/
      end
      talk "Inserting #{name_cfg} ..."
      open(files[matched_name]) do |name_cfg|   # copy file into cfgout
        while cfgline = name_cfg.gets
          cfgout.puts cfgline
          changes = true
        end
      end
      cfgout.puts end_line                      # output the end_line
    end
  end
end
cfgin.close
cfgout.close

if changes
  talk "There were changes."
  timestamp = Date.now().strftime("%F_%H.%M.%S")
  talk "#{cfgfile} saved with suffix of #{timestamp}"
  File.rename(cfgfile, cfgfile + ".#{timestamp}")
  talk "#{cfgfile} updated"
  File.rename(new_cfgfile, cfgfile)
else
  talk "No changes"
  File.unlink(new_cfgfile)
end
exit

Upvotes: 0

choroba
choroba

Reputation: 241868

Using the r (read file) command in sed:

sed -e '/#BEGIN mytest/r input' config 

Upvotes: 1

Related Questions