Find a unique line in the file, up the line and add?

Can someone please help me with this scenario? Am I looking for a SED or AWK command that I can use to find a unique line in a configuration file (Linux), go to a line and add a line to the end of this line?

For instance:

configuration file:

define hostgroup {
hostgroup_name http-urls; Host group name
HTTP URL alias Long name of group
members of domain1.com, domain2.com, domain3.com,
#MyUniqueString
}

In the above example, I would like to use SED or AWK to search for #MyUniqeString , go up the line starting with members and add "domain4.com" at the end of the line.

I found this question below, but I need to first search for a text file for the line, and go one line above.

Bash script: append text to the last character of a specific line in a file

Any suggestions?

+4
source share
5 answers

try this single line layer:

awk '{a[NR]=$0}/#MyUniqueString/{a[NR-1]=a[NR-1]"domain4.com"}END{for(i=1;i<=NR;i++)print a[i]}' configFile 

Test

 kent$ cat test.txt define hostgroup{ hostgroup_name http-urls ; The name of the hostgroup alias HTTP URLs ; Long name of the group members domain1.com, domain2.com, domain3.com, #MyUniqueString } kent$ awk '{a[NR]=$0}/#MyUniqueString/{a[NR-1]=a[NR-1]"domain4.com"}END{for(i=1;i<=NR;i++)print a[i]}' test.txt define hostgroup{ hostgroup_name http-urls ; The name of the hostgroup alias HTTP URLs ; Long name of the group members domain1.com, domain2.com, domain3.com,domain4.com #MyUniqueString } 
+1
source

You can do this efficiently with ed :

 ed yourfile <<-'EOF' /#MyUniqueString/ # Find the matching line - # Go up a line a # Append text domain4.com . # Stop appending .-1,.j # Join the line above with the appended line w # Write the line EOF 
+4
source

Comparison of three different solutions

Less using sed :

 sed -e ':a;N;/\n#MyUniqueString/{s/\n/ domain4.com\n/};H;s/\n.*$//;p;g;s/^.*\n//;ta;' config.file 

This can be run as:

 sed -e ' :a; N; /\n#MyUniqueString/{ s/\n/ domain4.com\n/ }; H; s/\n.*$//; p; g; s/^.*\n//; ta; ' config.file 

profiling:

 time sed ':a;N;/\n#MyUniqueString/{s/\n/ domain4.com\n/};H; s/\n.*$//;p;g;s/^.*\n//;ta;' config.file define hostgroup{ hostgroup_name http-urls ; The name of the hostgroup alias HTTP URLs ; Long name of the group members domain1.com, domain2.com, domain3.com, domain4.com #MyUniqueString } real 0m0.010s user 0m0.000s sys 0m0.008s 

Why not clean bash ?

Since there is no fork , this can be very fast (if from bash and for not too long configuration files):

 readarray configFile < ./config.file for ((i=${#configFile};i--;));do [[ "${configFile[i]}" =~ "#MyUniqueString" ]] && break done configFile[i-1]+=" domain4.com" printf "%s\n" "${configFile[@]//$'\n'/}" 

Profiling is performed:

 time { readarray configFile < ./config.file for ((i=${#configFile};i--;));do [[ "${configFile[i]}" =~ "#MyUniqueString" ]] && break done configFile[i-1]+=" domain4.com" printf "%s\n" "${configFile[@]//$'\n'/}" } 

It gives:

 define hostgroup{ hostgroup_name http-urls ; The name of the hostgroup alias HTTP URLs ; Long name of the group members domain1.com, domain2.com, domain3.com, domain4.com #MyUniqueString } real 0m0.001s user 0m0.000s sys 0m0.000s 

Test with awk

 time awk '{a[NR]=$0}/#MyUniqueString/{a[NR-1]=a[NR-1]" domain4.com"}END{for(i=1;i<=NR;i++)print a[i]}' config.file define hostgroup{ hostgroup_name http-urls ; The name of the hostgroup alias HTTP URLs ; Long name of the group members domain1.com, domain2.com, domain3.com, domain4.com #MyUniqueString } real 0m0.009s user 0m0.004s sys 0m0.000s 
+2
source

here's another sed solution using backlinks:

 sed '{N; N; s/\(.*\)\n\(#MyUniqueString\)/\1domain4.com\n\2/g}' config.file 
+2
source

This awk solution only needs to save the previous line

 awk ' /#MyUniqueString/ {prev = prev "domain4.com"} NR > 1 {print prev} {prev=$0} END {print prev} ' 
+1
source

All Articles