Yes, that's the way the :g command works. If you execute two :g commands after each other, do not be surprised, if they will be executed after each other :)
So you need to do it in one single pass. For that match the lines with a single :g command and then execute the # depending on the line content with different ranges. Something like this should work:
Be on a system with GNU Grep installed, then do:
:w !grep -o 'pattern'
The space between :w and !grep is important, because w!grep... means force-write to the file named grep ... even if it exists and is read-only.
Without using an external tool, what we can do is use a Vi implementation with decent "undo powers", like Vim. Then simply edit the ...
This is very simple. First, we set a mark at the bottom of the text. Let's use mark x:
Next, we transfer a copy of the lines we want to the bottom of the buffer:
Lastly, we delete lines 1 through to the mark:
Not sure if I've ever mentioned it on this site before, but I love macros! So, here's a solution that uses a recursive macro recording.
Starting from the top of the file, type:
Press "Return" here
How it Works
First clear the register x using normal mode
then delete the matched lines and 3 below it using append into register x.
:g/^xxx/d X 4
then erase the whole buffer
then paste x back into the buffer