CuriousCat
CuriousCat

Reputation: 275

How to exempt selected characters from substitution in Vim

I have this text:

"1-1-1"
"1-1-2"
"1-1-3"
"1-2-1"
"1-2-2"
"1-2-3"
"1-3-1"
"1-3-2"
"1-3-3"

I want to insert 0 on every line after the second hyphen, turning "1-1-1" into "1-1-01".

I tried substituting with :%s/-\d"/-0\d/ but that turns 1-1-1 into 1-1-0d.

How can I insert one symbol without changing the surrounding text?

Upvotes: 1

Views: 101

Answers (5)

Randy Morris
Randy Morris

Reputation: 40927

Just want to throw a different feature into the ring because I find it quite unique. Vim regular expressions have two zero-width atoms to designate the start (\zs) and end (\ze) of the text to be considered a match. You can use them in interesting ways, such as:

:%s/-\zs\ze\d"/0/

Which tells vim to replace the text between \zs and \ze (which happens to be empty here) with 0 if the rest of the regular expression matches.

Alternatively, using only \ze:

:%s/-\ze\d"/-0/

Which tells vim to replace - with -0 when the original - is followed by a digit and a double quote.

See :help \zs and :help \ze for more info.

Upvotes: 1

SergioAraujo
SergioAraujo

Reputation: 11800

It can be more simple:

:%s/\d\+"/0&

\d\+" ................ gets the last number and the close quote
0 .................... the wanted zero
& .................... let's get back the searched pattern

Another easy solution:

:%norm 2f-a0

% ................... whole file
norm ................ normal mode
2f- ................. jump to the second dash "-"
a ................... start insert on append mode
0 ................... the character we want insert

Upvotes: 0

Tim Biegeleisen
Tim Biegeleisen

Reputation: 521249

Try the following replacement:

:%s/-\(\d+\)"$/-0\1"/

Demo

The idea here is to match and capture the final digit in \1, then build the replacement using that capture group, with a prefixed zero.

Upvotes: 0

CuriousCat
CuriousCat

Reputation: 275

Thanks to Tim Biegeleisen for the answer!

The final RegEx was :%s/-\(\d+\)"$/-0\1"/

Basically his answer, except I had to escape each parenthesis with a backslash \

Breakdown: :%s + / + -\(\d+\)"$ + / + -0\1" + /

  • :%s: open substitute function for all lines in file
  • /: Begin pattern to search for
  • -\(\d+\)"$: search for all -, followed by one or more digits \d+, followed by the end of the line $

    • the parentheses () create a "capture group", and the backslashes \ escape the parentheses so they aren't interpreted literally
  • /: End pattern / Begin substitute string

  • -0\1": Substitute a hyphen(-0) followed by "capture group #1" (\1), followed by a quotation "
    • "capture group 1" is \d+; any pre-existing digits
    • since there is only one capture group, it's default number is 1
  • /: End expression

Upvotes: 0

builder-7000
builder-7000

Reputation: 7627

Starting in normal mode you could place the cursor on the last hyphen of the first line and use:

<c-v>GA0<esc>

Explanation:

  • <c-v>: Ctrl+v to enter block-visual mode
  • G: extend visual selection until the end of the file
  • A0: enter insert mode and put a 0
  • <esc>: Escape insert mode

More info in :help v_b_A

Upvotes: 0

Related Questions