2

The following will replace the first comma on each line with a pipe:

:%s/,/|/

How can I do the same for the last comma?

6

The best way to do this is to allow any character except for a newline, . any number of times, * followed by a comma ,. This gives us the following regex:

:%s/\(.*\),/\1|

Or, the more readable way:

:%s/\v(.*),/\1|

This works because * is "greedy" by default, meaning it will match as many characters as possible.

  • 1
    Clever! Why didn't I think of that. One more question: Sorry if this comes off as noobish, but why does this statement work without the final "/" in the replacement? – Jonathan Ericsson May 31 '16 at 22:30
  • 1
    @JonathanEricsson No worries! We've all been a noob at one point. :) In general, the last slash is never necessary, unless you need to specify a flag, like /g or /c. You could even do just this: :%s/, and the will remove the first comma on every line. – DJMcMayhem May 31 '16 at 22:32
  • 3
    This could be simplified to :%s/.*\zs,/|. – Karl Yngve Lervåg Jun 1 '16 at 6:13
4

Another one:

:s/,\ze[^,]\{-}$/|
  • 1
    Since you're using the lazy version, would .\{-} be enough? – muru Jun 1 '16 at 11:49
3

An alternative, just for the sake of it :)

%s/\v.*\zs,\ze[^,]*/|

This can be translated as: go search (s) on each line (%) for any number of chars (.*) followed by "a comma not followed by another one, i.e. followed by any other character, but comma" (,[^,]*). Using \zs and \ze around that one comma, we alter the match to only contain the character we want to act on. Therefore, the replacement part is simply the bar.

Edit/Update: of course, as Karl Yngve Lervåg mentions, the part after the comma isn't needed at all ..., so:

:%s/.*\zs,/|

... is the better incantation.

  • 1
    The part from \ze and on can be removed. – Karl Yngve Lervåg Jun 1 '16 at 6:12
  • 1
    Hah, so obvious apres coup :) – VanLaser Jun 1 '16 at 10:41
2

Oh, I'll jump on the bandwagon. I can't resist a good regular expression question. :)

Since really what we're trying to find is a "comma with no commas after it," i propose we use a negative lookahead.

:%s/,\(.*,\)\@!/|/g

This matches a comma only if it does not have .*, following it. However it only matches the comma since anything in a lookaround is only for context and not part of the match. Then we substitute it with a pipe, and our job is done.

1

I will prefer to go with a macro. Go to line 1 :1. Press qa to start recording in register A. Then, type $ to move to end of line. Then, F, or /,<CR>N to search backwards for a comma. Then, press r| to replace it with a bar. Press j to move to next line. Press @a to replay macro recursively. Then, stop macro by pressing q. (In cade, if The macro runs infinitely at the last line of file. You can abort it by pressing Ctrl+C.)

  • 1
    Cool solution, but this won't work if the comma is the last character on the line, or if one of the lines doesn't have a comma. – DJMcMayhem Jun 1 '16 at 6:16
  • I will check once and try to cover them too. – SibiCoder Jun 1 '16 at 6:18

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.