sed should process after a matching-pattern multiple commands which are given in braces like {cmd1;cmd2;cmd3}. But in the given code below, all commands followed after d(elite) are ignored.
script.sed
s/^\(interface GigabitEthernet0\)$/\1\/0/
/interface GigabitEthernet0\/0$/{
n # process next line = 1st line (after match) to be deleted
d # Should delete '1st line (after match) to be deleted'
n # process next line = 2nd line to be altered
s/2nd line to be altered/2ND LINE AFTER ALTERATION/
n
s/3rd line to be altered/3RD LINE AFTER ALTERATION/
}
input.txt
interface GigabitEthernet0
1st line (after match) to be deleted
2nd line to be altered
3rd line to be altered
4th line stays unchanged
sed -i -f script.sed example.txt
Expected output:
interface GigabitEthernet0/0
2ND LINE AFTER ALTERATION
3RD LINE AFTER ALTERATION
4th line stays unchanged
Effective output:
interface GigabitEthernet0/0
2nd line to be altered
3rd line to be altered
4th line stays unchanged
As seen in the output above, line 1st line (after match) to be deleted has been effectively deleted. But all following lines (2nd, 3rd, 4th) are not substituted.
BTW: Commands like a(ppend) or c(hange) behaves in the same manner; all followed commands are ignored.
sed is for doing s/old/new, that is all. Just use awk, e.g. with GNU awk for inplace editing (just like you're doing with GNU sed) and the switch statement:
$ cat tst.awk
/^interface GigabitEthernet0$/ { lineNr=1 }
lineNr%5 {
switch (lineNr++) {
case 1: $0 = $0 "/0"; break
case 2: next; break
case 3: sub(/2nd line/,"WHATEVER"); break
case 4: $0 = toupper($0); break
}
}
{ print }
$ cat file
interface GigabitEthernet0
1st line (after match) to be deleted
2nd line to be altered
3rd line to be altered
4th line stays unchanged
$ awk -i inplace -f tst.awk file
$ cat file
interface GigabitEthernet0/0
WHATEVER to be altered
3RD LINE TO BE ALTERED
4th line stays unchanged
And just in case you really do just want to print new lines instead of modify the existing ones in the range after you match your regexp (like in @AlexHarvey's sed answer), then that'd just be:
awk '/interface GigabitEthernet0/ {
print $0 "/0\n 2ND LINE AFTER ALTERATION\n 3RD LINE AFTER ALTERATION"
c = 4
}
!(c&&c--)' file
interface GigabitEthernet0/0
2ND LINE AFTER ALTERATION
3RD LINE AFTER ALTERATION
4th line stays unchanged
See the list of common awk idioms at https://stackoverflow.com/a/17914105/1745001 for what c&&c--
does.
Note that you don't have to specify the initial regexp multiple times, you don't have to worry about what chars might show up in your replacement text, and you can just give a number for how many lines are impacted you don't need to write the same character that number of times.
As it is stated in the POSIX sed specification, the command d
deletes the pattern space and starts the next cycle.
I tweaked your script a bit to get desired output:
/^interface GigabitEthernet0$/{
s//&\/0/
n
N
s/.*\n//
s/2nd line to be altered/2ND LINE AFTER ALTERATION/
n
s/3rd line to be altered/3RD LINE AFTER ALTERATION/
}
It works, but also shows us that sed is not the right tool for this job. So, as Ed suggested, use awk instead.
As noted by others, the immediate issue is that the d
command not only deletes, but also immediately ends the cycle, i.e. stops processing further commands.
But, there is a simpler sed solution available to you here. You seem to have over-complicated this, based on your apparent requirement.1
# test.sh
l1="interface GigabitEthernet0/0"
l2=" 2ND LINE AFTER ALTERATION"
l3=" 3RD LINE AFTER ALTERATION"
replacement="$l1\n$l2\n$l3"
sed '/interface GigabitEthernet0/ {N;N;N; s!.*!'"$replacement"'!}' example.txt
Output:
interface GigabitEthernet0/0
2ND LINE AFTER ALTERATION
3RD LINE AFTER ALTERATION
4th line stays unchanged
Further explanation:
/interface GigabitEthernet0/
,N;N;N
),/
with a character you trust not to appear in the input stream. I chose !
.1 And while I think there is an elegance to Ed's AWK solution, it is trivial to use sed here, where you just need to read forwards in a file by a few lines and do a s///
replacement.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With