BeastMaster64
BeastMaster64

Reputation: 167

How to replace line in a file after htting a particular line in bash

So I have a simple use case, I have a file like

line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
aaa
anything
anything
line_4
aaa

Now I have to replace the first aaa which comes after line_3.

Output-

line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
YES REPLACE THIS
anything
anything
line_4
aaa

I was able to replace anything on the very next line using-

sed -i '/line_3/{n; s/aaa/YES REPLACE THIS/}' file.txt

But aaa is not of the next line, I do not know after how many lines it occurs, any solution using sed, awk or anything bash related will work, any help will be appreciated.

Upvotes: 1

Views: 121

Answers (6)

Daweo
Daweo

Reputation: 36390

Using just replacement in perl, let file.txt content be

line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
aaa
anything
anything
line_4
aaa

then

perl -p -0777 -e 's/(line_3.*?)aaa\n/$1YES REPLACE THIS\n/s' file.txt

gives output

line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
YES REPLACE THIS
anything
anything
line_4
aaa

Explanation: -p and -e means work like sed, -0777 means shove whole file as single line. s/ - substitute, /s - make . also match newline character, I match line_3 and non-greedily any characters before aaa\n and replace all of that with what I matched before aaa\n denoted by ( and ) followed by YES REPLACE THIS\n.

(tested in perl 5.30.0)

Upvotes: 2

ikegami
ikegami

Reputation: 385655

This was proposed (by the currently-accepted answer):

perl -pe'$f = 1 if /^line_3$/; if ($f) { $f = 0 if s/^aaa$/YES REPLACE THIS/ };'

It simplifies to this:

perl -pe'$f ||= /^line_3$/; $f &&= !s/^aaa$/YES REPLACE THIS/;'

But the flip-flop operator does a lot of that work for us!

perl -pe'/^line_3$/ .. s/^aaa$/YES REPLACE THIS/'

See Specifying file to process to Perl one-liner.

Upvotes: 2

Shawn
Shawn

Reputation: 52344

ed is good for automated editing of files:

ed -s file.txt <<<EOF
/line_3/;/aaa/,.c
YES REPLACE THIS
.
w
EOF

Finds the first line matching line_3, then changes the first line after that matching aaa, and finally writes the modified file back out.

Upvotes: 1

sseLtaH
sseLtaH

Reputation: 11207

Using sed

$ sed '/line_3/,/line_4/{0,/^aaa/s/^aaa/YES REPLACE THIS/}' input_file
line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
YES REPLACE THIS
anything
anything
line_4
aaa

Upvotes: 2

M. Nejat Aydin
M. Nejat Aydin

Reputation: 10123

Using awk

awk '/line_3/{f=1} f&&/aaa/{$0="YES REPLACE THIS";f=0} 1' file

Upvotes: 4

zdim
zdim

Reputation: 66883

Set a flag once it sees line_3, unset it once it finds and replaces the pattern

perl -wpe'if ($on) { $on = 0 if s/aaa/XXX/ }; $on = 1 if /^line_3$/' file

This only prints the resulting lines to screen. If you want ot change the file ("in-place") add -i switch (perl -i -wpe'...'), or better -i.bak to keep a backup, too.

Upvotes: 3

Related Questions