0

I am searching for a particular string, and appending a series of lines following it. The sed command i have now is:

sed -i "
/CLIENTVERSION/ {
n
a\define service{
a\        use                     generic-service
a\        host_name               $var_hostname
a\        service_description     NSCLient++ Version
a\        check_command           check_nt!CLIENTVERSION
a\        }
}" windows.cfg;

The windows.cfg file contains service definitions for specific hosts. ( SBS and Test1 hosts are already in the file, and Test2 is the output after running my command. My output is:

define service{
    use                     generic-service
    host_name               sbs
    service_description     NSClient++ Version
    check_command           check_nt!CLIENTVERSION
    }
define service{
    use                     generic-service
    host_name               Test2
    service_description     NSCLient++ Version
    check_command           check_nt!CLIENTVERSION
    }
 define service{
    use                     generic-service
    host_name               Test
    service_description     NSCLient++ Version
    check_command           check_nt!CLIENTVERSION
    }
define service{
    use                     generic-service
    host_name               Test2
    service_description     NSCLient++ Version
    check_command           check_nt!CLIENTVERSION
    }

And I want:

define service{
    use                     generic-service
    host_name               sbs
    service_description     NSClient++ Version
    check_command           check_nt!CLIENTVERSION
    }
define service{
    use                     generic-service
    host_name               Test2
    service_description     NSCLient++ Version
    check_command           check_nt!CLIENTVERSION
    }
define service{
    use                     generic-service
    host_name               Test
    service_description     NSCLient++ Version
    check_command           check_nt!CLIENTVERSION
    }

I thought that the /g option did this, but i haven't instituted it and am uncertain as to why it is adding "Test2" service definition twice.

  • 1
    Please check [How to use sed to replace only the first occurrence in a file?](https://stackoverflow.com/questions/148451/how-to-use-sed-to-replace-only-the-first-occurrence-in-a-file) – Wiktor Stribiżew Feb 19 '19 at 21:21
  • `/g` means `repeat for every match across the whole line`. It's got nothing to do with matches across the whole file - matching on every line across the whole file is just what sed does by default. – Ed Morton Feb 19 '19 at 22:43

2 Answers2

1

You might find awk easier to work with. Using GNU awk for gensub() and multi-char RS:

$ cat tst.sh
#!/bin/env bash
infile="$1"

var_hostname="Test2"

awk -v RS='^$' -v ORS= '
NR==FNR { rec=$0; next }
{ print gensub(/CLIENTVERSION\n[^\n]+\n/,"&"rec,1) }
' - "$infile" <<!
define service{
    use                     generic-service
    host_name               $var_hostname
    service_description     NSCLient++ Version
    check_command           check_nt!CLIENTVERSION
    }
!

.

$ ./tst.sh file
define service{
    use                     generic-service
    host_name               sbs
    service_description     NSClient++ Version
    check_command           check_nt!CLIENTVERSION
    }
define service{
    use                     generic-service
    host_name               Test2
    service_description     NSCLient++ Version
    check_command           check_nt!CLIENTVERSION
    }
define service{
    use                     generic-service
    host_name               Test
    service_description     NSCLient++ Version
    check_command           check_nt!CLIENTVERSION
    }

Just change awk to awk -i inplace for inplace editing (like `sed -i) if you like. The above was run on this input file:

$ cat file
define service{
    use                     generic-service
    host_name               sbs
    service_description     NSClient++ Version
    check_command           check_nt!CLIENTVERSION
    }
define service{
    use                     generic-service
    host_name               Test
    service_description     NSCLient++ Version
    check_command           check_nt!CLIENTVERSION
    }
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

The approach borrowed from this answer works here:

sed -i "
/CLIENTVERSION/ {
n
a\define service{
a\        use                     generic-service
a\        host_name               $var_hostname
a\        service_description     NSCLient++ Version
a\        }
:a;n;ba}" windows.cfg

The difference is in the last line of the script, which puts it into a loop that silently reads the rest of the file without any processing.

Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175