问题
Can someone please help me with this scenario? I'm looking for a SED or AWK command that I can use to find a unique string within a config file (Linux), go up a line and append a string to the end of that line?
For example:
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,
#MyUniqueString
}
In the above example, I'd like to use SED or AWK to find #MyUniqeString, go up a line that starts with members and append "domain4.com" at the end of the line.
I found this question below but I need to search the text file first for the string, and go one line above.
Bash script: Appending text at the last character of specific line of a file
Any suggestions?
回答1:
try this one-liner:
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
}
回答2:
You can do this effectively 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
回答3:
here's another sed solution using backreferences:
sed '{N; N; s/\(.*\)\n\(#MyUniqueString\)/\1domain4.com\n\2/g}' config.file
回答4:
Comparission of three different solutions
Smaller, using sed:
sed -e ':a;N;/\n#MyUniqueString/{s/\n/ domain4.com\n/};H;s/\n.*$//;p;g;s/^.*\n//;ta;' config.file
This could 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 pure bash ?
As there is no fork, this could be very quick (if from bash and for not too long config 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 run by:
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'/}"
}
Will give:
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
回答5:
This awk solution only requires the previous line is remembered
awk '
/#MyUniqueString/ {prev = prev "domain4.com"}
NR > 1 {print prev}
{prev=$0}
END {print prev}
'
来源:https://stackoverflow.com/questions/13958903/find-unique-string-within-a-file-up-a-line-and-append