Reputation: 12487
I have the following code:
function replaceappend() {
awk -v old="^$2" -v new="$3" '
sub(old,new) { replaced=1 }
{ print }
END { if (!replaced) print new }
' "$1" > /tmp/tmp$$ &&
mv /tmp/tmp$$ "$1"
}
replaceappend "/etc/ssh/sshd_config" "Port" "Port 222"
It works perfectly but I am looking to modify it so it replaces the entire lines contents rather than just the matching text.
At the moment it would do this:
Port 1234 -> Port 222 1234
I want it to be work like this:
Port 1234 -> Port 222
I closest code I can find to do this is found here:
awk 'NR==4 {$0="different"} { print }' input_file.txt
This would replace the entire line of the match with the new content. How can I implement this into my existing code?
Upvotes: 0
Views: 4414
Reputation: 74596
If you want to replace the entire line you can simplify your function. To avoid problems with metacharacters in the variables you pass to awk, I would suggest using a simple string search too:
awk -vold="$2" -vnew="$3" 'index($0,old)==1{f=1;$0=new}1;END{if(!f)print new}' "$1"
index
returns the character position of the string that you are searching for, starting at 1. If the string old
is at the start of the line, then the line is changed to the value of new
. The 1
after the block is always true so every line is printed (this is a common shorthand for an unconditional {print}
block).
As mklement0 has pointed out in the comments, the variables you pass to awk are still subject to some interpretation: for example, the string \n
will be interpreted as a newline character, \t
as a tab character, etc. However, this issue is much less significant than it would be using regular expressions, where things like a .
would match any character.
Upvotes: 2
Reputation: 203169
Just change:
sub(old,new) { replaced=1 }
to:
$0~old { $0=new; replaced=1 }
or:
sub(".*"old".*",new) { replaced=1 }
Upvotes: 3
Reputation: 10865
Again, use a regular expression for that which you want to replace:
replaceappend port.txt "Port.*" "Port 222"
Here you are replacing Port (if it starts the line, as per your function definition) plus whatever follows until the end of the line with "Port 222".
EDIT: To make this part of the function instead of requiring it in the call, modify it to
function replaceappend() {
awk -v old="^$2.*" -v new="$3" '
sub(old,new) { replaced=1 }
{ print }
END { if (!replaced) print new }
' "$1" > /tmp/tmp$$ &&
mv /tmp/tmp$$ "$1"
}
Upvotes: 1