1

I have a whole bunch of files with certain patterns

ABCD: 
Something 1 
Anything 2

EFGH:
Something 3
Anything 4

ABCD:
Something 5
Anything 6

HIJK:
Something 7
Anything 8

I want to retain the second line after ABCD and delete everything else in all these files. On a single file, this can be achieved using vim by the following commands

/ABCD\_[^a-zA-Z] (*searches the pattern*)
qaq              (*flush register*)
:g//norm! "A3Y   (*yank 3 lines including pattern into register A*)
ggVG"ap          (*delete everything else*)

Then I can perform some easy regex searches to delete the ABCDs and Somethings to be left with the correct Anythings.

However using args and argdo as suggested here for multiple files throws up errors "Not an editor command" at the second operation above. Same thing happens if I bypass the second, and go directly to the third and fourth. I am performing args and argdo after each step.

Any recommendations staying within or going beyond vim?

2

Try making the whole thing into one giant normal! command:

:argdo norm! /ABCD\_[^a-zA-Z]<C-v><CR>qaq:g//norm! "A3Y<C-v><CR>ggVG"ap

Using <C-v><cr> allows you to enter a literal carriage return. This fixes your problem, but there's still a lot of things about your approach that isn't ideal.

For example:

  • There's no need to search for something, and then use :g//. Instead, just use :g/ABCD\_[^a-zA-Z] instead.

  • You can use \_A instead of \_[^a-zA-Z]

  • There is no need to make the global command do a normal command. Instead, do an ex command and you won't need to clear register 'a'. So do :g/ABCD\_A/3ay.

Putting all of this together, I'd recommend

:argdo norm! :g/ABCD\_A/3ya<C-v><CR>ggVG"ap
1

Since you are also looking for an answer using awk:

awk '/ABCD/ {getline; getline; print}' input

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.