2

I was wondering if it's possible to use the :g command in vim to match with only the first occurrence of a search result.

I have a file with contents like

Match 01
    stuff 01
    stuff 02
    stuff 03
Match 01
    stuff 01
    stuff 02
    stuff 03
Match 02
    stuff 01
    stuff 02
    stuff 03
Match 02
    stuff 01
    stuff 02
    stuff 03
Match 03
    stuff 01
    stuff 02
    stuff 03
Match 03
    stuff 01
    stuff 02
    stuff 03

I'm trying to execute the following command to extract data

:g/Match 02/.,$w! /tmp/TESTING.txt

So it's using the global command then writes from the current line to the end of the document into /tmp/TESTING.txt

The current line though is always the last occurrence of the match so I end up with

Match 02
    stuff 01
    stuff 02
    stuff 03
Match 03
    stuff 01
    stuff 02
    stuff 03
Match 03
    stuff 01
    stuff 02
    stuff 03

Instead of

Match 02
    stuff 01
    stuff 02
    stuff 03
Match 02
    stuff 01
    stuff 02
    stuff 03
Match 03
    stuff 01
    stuff 02
    stuff 03
Match 03
    stuff 01
    stuff 02
    stuff 03

Which is what I want. I was wondering if it's possible to have the global command only go to the first occurrence of the match to solve this.

  • That's weird i thought I did, must've fumbled. Tganks for reminding me – TheLovelySausage Jan 21 '18 at 15:12
3

Sounds like your problem is that the cursor has ended up below the first match; my suggestion would be to tell vim to move the cursor to line 1, then execute the range/write:

:1 | /Match 02/,$w! /tmp/TESTING.txt

I removed the period, since it seems to me that you want to write a range to a file, and that range is defined as from the search on "Match 02" until the end $ of the file.

Reference:

  • This works perfectly, I didn't realize you could use find and pipes like that. Thanks so much for the assistance – TheLovelySausage Jan 18 '18 at 7:04
2

This appears to work for me. The problem with your incantation appeared to be that the global match was matching the latter match (as it was, well, global):

0;/Match 02/;,$w! file
2

Global executes the command for each match, so what is actually written to the file is .,$ from the first match, and then .,$ from the second match (etc). This can be observed by appending to the output file instead of clobbering the contents on each match.

:g/Match 02/.,$w >> TESTING

A macro may be more suitable; type

qa1G/Match 02
:.,$w! TESTING
q

where the line breaks above are where you need to mash the return key. Then type :reg a and this should look something like

:reg a
--- Registers ---
"a   1G/Match 02^M:.,$w! TESTING^M

and can be played back by typing @a

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.