This is a perfect use case for
ex, the POSIX-specified tool of choice for file editing.
(If you've ever used
vi, by the way, you are likely familiar with
ex since everything you type in
vi that starts with a colon
: is an
ex is the predecessor of
printf %s\\n 'g/NAME#AAAA/ /AGE/t- | s/^/#/ | /AGE/s/.*/AGE NIL/' x | ex input.txt
If you want to test it before you actually save the file, change the final
x before the pipe symbol into
%p and the modified file won't be saved, but the modified version will be printed to
stdout. So here is the testing command:
printf %s\\n 'g/NAME#AAAA/ /AGE/t- | s/^/#/ | /AGE/s/.*/AGE NIL/' %p | ex input.txt
printf %s\\n provides an easy way to feed multiple commands to
ex with a newline after each.
g/regex/ is the global command; it runs the commands which follow (up to the next newline) on each line that matches the given regex.
/AGE/t- copies the next line which matches the pattern
/AGE/ to a position just before the current line (which is the
NAME#AAAA line). It also moves the cursor to the new copy of the line (so that now becomes the "current line").
| is a command separator in
s/^/#/ prefixes the copied
AGE line with a hashtag. (Or a pound sign, depending on your dialect.) ;)
The next command really has two parts:
/AGE/ is the address, which makes this command operate on the next line which contains that pattern, and
s/.*/AGE NIL/ replaces whatever that line was, with
x saves the changes to the file and exits.
Reversing the changes
To reverse the changes, I would do the following:
printf %s\\n 'g/NAME#AAAA/ ?^#AGE? m /^AGE/ | s/^#// | -d' %p | ex input.txt
Then when the change was verified, actually save the changes with:
printf %s\\n 'g/NAME#AAAA/ ?^#AGE? m /^AGE/ | s/^#// | -d' x | ex input.txt
Global command as before.
Take the line that starts with
#AGE from before the NAME line, move it after the next line that starts with
Remove the leading
Delete the immediately preceding line with
-d (which is the NIL age line).
Print or save changes.