5

Here is my data:

{ team: 'NYY', result: 'L', rs: 1,6 },
{ team: 'NYY', result: 'W', rs: 4,3 },
{ team: 'NYY', result: 'L', rs: 3,6 },
{ team: 'NYY', result: 'L', rs: 5,6 },
{ team: 'NYY', result: 'L', rs: 4,8 },
{ team: 'NYY', result: 'W', rs: 14,4 },
{ team: 'NYY', result: 'W', rs: 6,5 },
{ team: 'NYY', result: 'L', rs: 3,4 },
{ team: 'NYY', result: 'L', rs: 5,7 },
{ team: 'NYY', result: 'W', rs: 5,4 },
{ team: 'NYY', result: 'W', rs: 9,0 },
{ team: 'NYY', result: 'W', rs: 5,3 },

I would like to replace the last comma in each line so the line looks like this:

{ team: 'NYY', result: 'L', rs: 1, ra: 6 },

Can I use :%s to accomplish this?

3 Answers 3

12

Peter's answer achieves the result that you want, but not necessarily the question that you asked.

This regular expression will match the Nth occurrence of your PATTERN:

\(.\{-}\zsPATTERN\)\{N}

To unpack that a little bit, it matches everything non-greedily (that's what the {-} is) though each PATTERN N times (that's what the {N} is)

The \zs marks the start of what you want to replace. In the example above, you would end up replacing the comma with whatever your replacement text is. You could put the \zs after the pattern to add your replacement after the comma.

To give a more concrete example with your data,

%s/\(.\{-},\zs\)\{3}/ ra: /

would add in the text after the third comma.

That being said, this doesn't really seem to be the best approach for this particular problem. Here, you could insert your "ra" in between any comma followed by a digit:

%s/,\zs\ze\d/ ra: /g

Or use a macro to find the Nth occurrence and insert:

3f,a ra:

Or use Tabular to align your commas, and then do a block select (ctrl+v) to insert your text:

Tab /,

etc.

1
  • Awesome answers, the both of you. Apr 20, 2016 at 15:20
6

Using \ze makes this pretty easy. Just match the end of the line so digit followed by ending curly bracket.

%s/\ze\d\+ }/ ra: /

\ze sets the end of the matched area. For more help see :h /\zs & :h \ze.

1
  • "For more help see :h /\zs", I think you meant :h /\ze instead.
    – isAif
    Jul 7, 2021 at 17:24
2

Summary: You could record and apply the macro 03f,a ra: <Esc>j.

The regular expression answers above are very good performance wise. However, for quick substitutions I would suggest using macro's. Above can be done by defining and applying the following macro:

  1. Go to first line containing the to be edited text.
  2. Start recording macro to, lets say,tqt
  3. Jump to start of line ⇒ 0
  4. Jump to third occurrence of ,3f,
  5. Append ra: behind cursor ⇒ a ra: (note the space behind :)
  6. Go to the next row ⇒ <Esc>j
  7. Save the macro ⇒ q
  8. Run the macro, lets say, 100 times ⇒ 100@t

(For people new to Vim: If you are using Vim for some time, then creating a similar macro and applying it takes less than a minute.)

4
  • Welcome to Vi and Vim! Nice answer. I'd suggest removing spaces between keys (q t becomes qt, etc.) and using "vim key notation" (Enter becomes <CR>)—it's more standardized across the site, and it helps not confuse new users who might type the spaces.
    – D. Ben Knoble
    Oct 17, 2019 at 21:06
  • Also note that /,<CR>nn in the same line is more concisely 3f,; v/}<CR>hh can be vt}h; I<Esc> can be 0. The escape in (5) is unnecessary.
    – D. Ben Knoble
    Oct 17, 2019 at 21:07
  • Lastly, OP wants to insert text, not delete, so maybe qt03f,i ra: <Esc>j ?
    – D. Ben Knoble
    Oct 17, 2019 at 21:09
  • 1
    Thanks for your suggestions! Learned some new tricks. 3f, is great. Also, I indeed misinterpreted the question. Should all be fixed now.
    – RikH
    Oct 18, 2019 at 7:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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