Rick H
Rick H

Reputation: 1

SED Assistance Needed

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

Answers (2)

Ruslan Osmanov
Ruslan Osmanov

Reputation: 21492

If you only want to replace all DROPs for an iptables chain with ACCEPTs, 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

Cyrus
Cyrus

Reputation: 88573

With GNU sed:

sed -i -r 's/(:INPUT )DROP( \[0:0\])/\1ACCEPT\2/' file

Upvotes: 1

Related Questions