/two/{
:loop
N
/\(\(.*\n\)\{5\}\).*/{
s//\1Modified/
b
}
b loop
}
Save that in x.sed
and execute it as
sed -f x.sed file
or use the one-liner for GNU Sed:
sed '/two/{:a;N;/\(\(.*\n\)\{5\}\).*/{s//\1Modified/;b;};ba;}' file
Line by line analysis:
- 1-2: When the match is found, start a loop. In this loop,
- 3: Add a line to pattern space with the
N
command.
- 4: If there are 5 newline characters — the basic regex is
\(.*\n\)\{5\}
—,
put that in a capture group, leave the last line (.*
) uncaptured and
- 5: Substitute the whole pattern space* with the capture
group followed by the
Modified
line.
- 6: Break the loop.
- 8: Else
loop
again.
*An empty regex slot is equivalent to the previously used regex,
so that 5th line is equivalent to s/\(\(.*\n\)\{5\}\).*/\1Modified/
.
Less esoteric is to use Awk:
awk '{c--};/two/{c=5};c==0{$0="Modified"};{print}' file
That starts by decrementing a c
ounter, and because, as all variables, c
is
initially zero, it only becomes positive if a match is found.
An even more explicit approach would be
awk 'BEGIN{c=-1};/two/{c=5};c==0{$0="Modified"};{print};c>=0{c=c-1}' file
Useful Sed resources:
end
could be replaced with$
, so for exampleseq 10|sed '/2/,${/2/,+5{/2/,+4!s/.*/replaceString/}}'
from accepted answer orseq 10| sed '/2/{:a;N;$!ba;s/[^\n]*/replaceString/6}'
from the second answer. no such big difference, but easy adjustable if one could understood how they works. BTW, I retracted my close vote.t
. Different answers you have will give you the same output fortwo
but different output fort
. It would also be good if you showed if you want a regexp or string match.MODIFIED
it werefifty-two
? Should THAT line then match withtwo
and so you'd change the 5th line after THAT and every 5th line from then on?