Search code examples
regexvim

delete everything but the pattern and the next line vim


Trying to figure out how to delete everything except a pattern from vim using the regex capabilities.

Specifically, I'm trying to delete everything but the "United States" line as well as the line immediately following it (from the Arch Linux Mirrorlist). So this...

## Austria
Server = http://mirror.easyname.at/archlinux/$repo/os/$arch
## United States
Server = http://mirror.cs.pitt.edu/archlinux/$repo/os/$arch
## Thailand
Server = http://mirror2.totbb.net/archlinux/$repo/os/$arch

Should transform into this... (and continue this for every instance of the United States line)

## United States
Server = http://mirror.cs.pitt.edu/archlinux/$repo/os/$arch

The line I've attempted to use to complete this is:

:v/## United States\n\_.\{-}\_$/d

If I understand correctly, :v selects everything but the pattern. The pattern I'm trying to feed it is the United States line plus the next line (\n) and everything after that to the end of the line (\_.\{-}\_$) and then delete all this junk (/d).

However, when executing that line I get only the lines with the United States. Something like this:

## United States
## United States
## United States
...

What should I do to save the line after the United States line?


Solution

  • If I understand correctly, :v selects everything but the pattern. The pattern I'm trying to feed it is the United States line plus the next line (\n) and everything after that to the end of the line (\_.\{-}\_$) and then delete all this junk (/d).

    Close. But not quite. There's a subtle distinction. :v (or :g!) will run a particular command on every line that does not match the regex. Which is really really close to what you want, just not quite there. Here's the problem. The line:

    ## United States
    

    does match your regex, this is true. Therefore, this line does not get deleted. However, the line right after this then gets tested, and

    Server = http://mirror.cs.pitt.edu/archlinux/$repo/os/$arch
    

    Does not match your regex. So it does get deleted.

    The easiest solution I can think of is to match every location line (So your lines starting with ## <location>) other than ## United States, and then for each of those matches, delete that line and the following. For example:

    :g/## \(United States\)\@!/,+1d