3

I am very new to vim, and I have a csv file with this format :

"1006","text:xxx"
"2007","text:xxx"
"3008","text:xxx"
"4009","text:xxx"
"5001","text:xxx"

every "xxx" is replaced by an increment+1 of numbers at the start of each line. athe result should be like this:

"1006","text:1007"
"2007","text:2008"
"3008","text:3009"
"4009","text:4010"
"5001","text:5002"
6

You could use a substitution command like this one:

:%s/"\(\d\+\).*:\zs.\+\ze"/\=submatch(1)+1

The command can be decomposed in these several parts:

  • % is the range of lines you want to apply the command to. % is all the lines in the buffer, check :h :range for more options
  • s/ [...] / [...] is the substitution which will replace the first part by a second one
  • "\(\d\+\).*:\zs.\+\ze" This is the part used to match the text you want to act on, several things are going on here:
    • " is the first litteral " before the number you want to increment
    • \d\+ is the number you will need to increment
    • the number is surrounded by \( ... \) to tell vim that we should capture this value to reuse it later on
    • .*: are all the characters between the end of your number and the xxx you'll need to replace
    • \zs ... \ze are used to say to vim that the part we actually want to change is between these two markers see :h /\zs and :h /\ze
    • .\+ inside the \zs ... \ze is are all the characters we want to replace (your xxx)
  • \=submatch(1)+1 is the second part of the command: what we will replace our text with
    • \= indicates that we will replace with the result of the evaluated expression following on. See :h sub-replace-expression
    • submatch(1) is used to get the value of the captured string in the first part. :h /\=
    • and finally +1 is used to increment the value
| improve this answer | |
  • 1
    Just want to add that if you want to divide the captured number by some value, you may want to change the substitute delimiter to another character, for example, #, to avoid a clash with division character /. – jdhao Jan 10 at 14:21
5

You can do this with a macro. Start by placing your cursor at the very start of the file gg and then type the following:

qqyi"2fxviwpCtrl-Aq

This records a macro that will update a single line in the way you require. Then undo your changes uu and play the macro on every line of the file by entering the command:

:%norm @q

How the macro works:

  • qq Start recording a macro into register "q.
  • yi" Yank the contents of the next double-quoted string on the line.
  • 2fx Jump to the second x after the cursor.
  • viw Visually select the word xxx.
  • p Replace the visual selection with the yanked text.
  • Ctrl-A Increment the number.
  • q Stop recording.
| improve this answer | |

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.