Whenever you see records separated by blank lines ("paragraphs", if you like), Perl's "paragraph mode" is often a good solution:
$ perl -00lpe 'if(/NAME#AAAA/){s/\bAGE\s/#$&/; s/$/\nAGE NIL/;}' file
NAME#AAAA
STD 1
SEC A
#AGE 5
AGE NIL
NAME#BBBB
STD 2
SEC B
AGE 6
NAME#CCCC
STD 3
SEC C
AGE 7
NAME#AAAA
STD 4
#AGE 9
AGE NIL
NAME#AAAA
STD 7
SEC A
#AGE 12
AGE NIL
Explanation
-00
: this activates perl's paragraph mode, where each "paragraph" (group of non-blank lines until a blank one) is treated as a "line".
-l
: removes trailing newlines from each input record (each paragraph) and adds a newline to each print
call.
-pe
: print each input record aftrer applying the script given by -e
to it.
So, those flags make perl
read over the input file, applying the script to each record, and then printing the result. The script itself does:
if(/NAME#AAAA/)
: if this record matches NAME#AAAA
.
s/\bAGE\s/#$&/
: The s/foo/bar/
is the substitution operator. It will replace foo
with bar
. Here, I am replacing AGE
with itself preceded by a #
. The \b
matches word boundaries, and will exclude things like ADAGE
from the match. The $&
is a special variable and means "whatever was matched. So, s/\bAGE\s/#$&/
will replace AGE
with #AGE
.
s/$/\nAGE NIL/
: The $
matches the end of the record. So replacing it with something else will append to the end of the record. This command appends AGE NIL
to the end of the matched record.
Note that all operations here are case sensitive. If you need case insensitive matching use this instead:
perl -00lpe 'if(/NAME#AAAA/i){s/\bAGE\s/#$&/i; s/$/\nAGE NIL/i;}' file