Reputation: 1
I am trying to write a script which will modify a line within a file based on a string. I cannot determine the correct sed syntax if the string contains both spaces and brackets.
Original String:
:INPUT DROP [0:0]
Change Needed:
:INPUT ACCEPT [0:0]
I have written the following and it works; however, because it only mathces a partial string, I'm afraid it could modify other lines within the file unintentionally. I want to match the entire string to avoid that.
#!/bin/bash
File=/etc/sysconfig/iptables
String=":INPUT"
sed -i -e "/$String/ s/DROP/ACCEPT/" $File
Upvotes: 0
Views: 43
Reputation: 21492
If you only want to replace all DROP
s for an iptables chain with ACCEPT
s, use an anchor for the beginning of the line:
String=':INPUT'
sed -i -e 's/^\( *'"$String"' *\)DROP/\1ACCEPT/' "$File"
The command captures the $String
pattern at the beginning of the line (^
) with a number of optional spaces (*
) around, and refers to the captured content with \1
.
If, however, you want to match the entire line, use an anchor for the end of line ($
) as well:
sed -i -e 's/^\( *'"$String"' *\)DROP\( *\[0:0\] *\)$/\1ACCEPT\2/' "$File"
You likely want to make the expression slightly more flexible by allowing any number of digits for the [<packet-counter>:<byte-counter>]
pair, since the counters are of no importance for the logic of the iptables rules:
sed -i -e 's/^\( *'"$String"' *\)DROP\( *\[[0-9]\+:[0-9]\+\]\)$/\1ACCEPT\2/' \
"$File"
The command above replaces the entries of a saved iptables file as follows:
< :INPUT DROP [0:0]
< :INPUT DROP [618709275:676424577017]
---
> :INPUT ACCEPT [0:0]
> :INPUT ACCEPT [618709275:676424577017]
Also note the use of double quotes. Enclosing a variable in double quotes prevents reinterpretation of special characters, except $
, backtick, and \
. Otherwise, you risk to apply the command to multiple files (if, for instance, $File
contains a *
).
Upvotes: 0
Reputation: 88573
With GNU sed:
sed -i -r 's/(:INPUT )DROP( \[0:0\])/\1ACCEPT\2/' file
Upvotes: 1