with your script result are:
dog1!cat!
dog2!NULL!
dog1!fish!
dog2!NULL!
but my expected result are from:
dog1!cat!
dog2!bird!
dog1!fish!
dog2!lion!
...
to:
dog1!bird!
dog2!NULL!
dog1!lion!
dog2!NULL!
...
do you see differences?
I guess you are using original "vi", not "vim" on which I tested this command... Does it have to be done in vi? If not, you can try something like this: