add a line between matching pattern - unix

Viewed 93

I want to insert "123" below madguy-xyz- line in "module xyz". There are multiple modules having similar lines. But i want to add it in only "module xyz".

module abc 
    njkenjkfvsfd
    madguy-xyz-mafdvnskjfvn
    enfvjkesn
endmodule

module xyz
    njkenjkfvsfd
    madguy-xyz-mafdvnskjfvn
    enfvjkesn
endmodule

This is the code i tried but doesn't work,

sed -i "/module xyz/,/^endmodule/{/madguy-xyz-/a 123}" <file_name>

This is the error I got: sed: -e expression #1, char 0: unmatched `{'

4 Answers

This might work for you (GNU sed):

sed '/module xyz/{:a;n;/madguy-xyz-/!ba;p;s/\S.*/123/}' file

For a line containing module xyz, continue printing lines until one containing madguy-xyz-.

Print this line too and then replace it with 123.

Another alternative solution:

sed '/module/h;G;/madguy-xyz.*\nmodule xyz/{P;s/\S.*/123/};P;d' file

Store any module line in the hold space.

Append the module line to each line.

If the first line contains madguy-xyz- and the second module xyz, print the first then substitute the second for 123.

Print the first line and delete the whole.

With your shown samples, please try following.

awk '1; /^endmodule$/{found=""};/^module xyz$/{found=1} found && /^ +madguy-xyz-/{print "123"} ' Input_file

Once you are happy with results of above command, to save output into Input_file itself try following then:

awk '1;/^endmodule$/{found=""} /^module xyz$/{found=1} found && /^ +madguy-xyz-/{print "123"} ' Input_file > temp && mv temp Input_file

Explanation: Adding detailed explanation for above.

awk '                      ##Starting awk program from here.
1;
/^endmodule$/{found=""}    ##Printing current line here.
/^module xyz$/{            ##Checking condition if line contains module xyz then do following.
  found=1                  ##Setting found to 1 here.
}
found && /^ +madguy-xyz-/{   ##Checking if found is SET and line contains madguy-xyz- then do following.
  print "123"              ##Printing 123 here.
}
' Input_file               ##Mentioning Input_file name here.

NOTE: In case your line exactly having module xyz value then change above /module xyz/ (this condition) to $0=="module xyz" too.

With GNU sed I suggest:

sed -i -e "/module xyz/,/^endmodule/{/madguy-xyz-/a 123" -e "}"  file

Using any POSIX awk in any shell on every Unix box, the following will work for the sunny day case in your question and all rainy day cases such as the ones I mentioned in my comment and more:

$ cat tst.awk
{ print }

$1 == "endmodule" {
    inMod = 0
}

inMod && (index($1,old) == 1) {
    sub(/[^[:space:]].*/,"")
    print $0 new
}

($1 == "module") && ($2 == mod) {
    inMod = 1
}

$ awk -v mod='xyz' -v old='madguy-xyz-' -v new='123' -f tst.awk file
module abc
    njkenjkfvsfd
    madguy-xyz-mafdvnskjfvn
    enfvjkesn
endmodule

module xyz
    njkenjkfvsfd
    madguy-xyz-mafdvnskjfvn
    123
    enfvjkesn
endmodule
Related