7

I have a bunch of data, and I want to yank everything that matches the following regex to a register :

/'user': '[a-Z]*'

Is there any way to copy all the matches to a register in vanilla vim? I've looked at this question, but it only works for one result, after pressing 'n' to go to the next result, it will use '//e' again and go to the end of the next result, instead of the beginning.

I've also looked at this SO question. It's almost exactly what I'm looking for, except I can't figure out how to change it to work with particular matches instead of the lines they are on.

2
  • Is there ever more than one match per line?
    – evilsoup
    Sep 29, 2014 at 16:29
  • Yes, multiple matches per line Sep 29, 2014 at 16:31

4 Answers 4

10

This can be simply achieved, by running a :s command with the n flag set (which basically says, to not replace anything (but by using an \= in the replace part, you can still capture the matches (see :h sub-replace-special). So first let's clear register A:

qaq

Then you can capture your maches into register a by using:

:%s/'user': '[a-Z]*'/\=setreg('A', submatch(0), 'V')/gn

And paste your matches:

:put A

This needs at least Vim 7.4 (I forgot the actual patch number).

4
  • This puts each match on its own line, which is useful behavior most of the time. Being a single ex-mode command, it'll also be faster than my macro for really large files. +1.
    – evilsoup
    Sep 30, 2014 at 8:46
  • Well, you can of course capture it in a list and then later do whatever you want with that. That was just an example since the OP did want to capture it in a register. Sep 30, 2014 at 9:01
  • I think this needs to be changed to [a-zA-Z], at least on vim 8.1, otherwise vim says something about reverse character in range. Nov 15, 2019 at 21:56
  • @TankorSmash this might depend on the locale Nov 17, 2019 at 16:28
2

" clear the 'a' register

qaq

" global search and yank all lines ('A') into the 'a' register.

:g/'user': '[a-Z]*'/y A

Modify the part between :g/ and /y A as needed.

" paste into another file

"aP

4
  • The data is all on one line Sep 30, 2014 at 18:18
  • There should be one line per line found. If there are multiple instances of the found string per line, then both will be listed in the same output line. Sep 30, 2014 at 18:23
  • I mean, the text, all the data, is just one line, wouldnt this just yank that one line? Sep 30, 2014 at 18:24
  • Yes, I did not know your data was one long line. Sep 30, 2014 at 18:32
0

You can use the :YankMatches command from my ExtractMatches plugin:

:%YankMatches /'user': '[a-Z]*'/

Each match is put on a new line by default; to use another separator, there's an alternative form.

2
  • Does this plugin really works? A lot of errors with the command %YankMatches /re.sub([^)]*)/
    – hhh
    Aug 10, 2017 at 12:11
  • 1
    @hhh: You also need to install my ingo-library plugin. It's listed as a DEPENDENCY in the plugin's INSTALLATION section. Aug 10, 2017 at 12:18
0

There's probably a better way (these are inefficient if we're talking about a really large number of entries -- it should be fine so long as we're not talking thousands and thousands), but the first thing that comes to mind is a recursive macro. First, turn of the wrapscan option so that searches that reach the end of the file won't loop around to the beginning again (otherwise you'll end up with an infinite loop):

:set nowrapscan

Then, make sure you have two clear registers:

qqq
qaq

Now, the magic:

qq/'user': '[a-Z]*'
"Ay//e
@qq

qq starts recording all your keystrokes to the register q. Using a capital letter makes vim append to that register rather than overwriting it. y//e yanks to the end of your search. @q calls the (currently-empty) q register as a macro, and the final q stops the recording. Then, simply:

@q

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .