Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use regex in vim to replace with an incrementing number variable

Tags:

regex

vim

vi

I have a file which content like this:

id      phone   name
x'1234' 12345   jack
x'4567' 45678   Jojo
x'7890'  89456  Dio
x'4591'  34872  joseph

and i want to parse it into like this:

id  phone   name
1   12345   jack
2   45678   Jojo
3    89456  Dio
4    34872  joseph

I know basic regular expression could replace all id to any string like this:

:%s/x'\(\w\+\)'/1/g

and it will become:

id  phone   name
1   12345   jack
1   45678   Jojo
1    89456  Dio
1    34872  joseph

How to replace id to an increment variable ?

like image 422
a4fz067lu Avatar asked Sep 02 '19 11:09

a4fz067lu


2 Answers

Mind that you can use an expression as the replacement string in the substitute command (:s). When the replacement string starts with \= it is evaluated as an expression.

Here, one possible solution is

:let i=1 | g/^x'\d\+'/s//\=i/ | let i=i+1

It finds all occurrences (one per line) of the ^x'\d\+' pattern and replaces it with the value if i that is incremented each time the match is found. As has been noted in comments, the | is a part of the g replacing "code", as "| is used to execute more than one command at a time".

Another solution is using the line() command (taking into account that your file has a header top line, so you should actually subtract 1 from the value returned with line()):

%s/^x'\d\+'/\=line('.')-1/

The ^x'\d\+' regex matches

  • ^ - start of a line
  • x' - x' string
  • \d\+ - 1+ digits
  • ' - a ' char.

There are other interesting "increment number in regex" examples at the Using an expression in substitute command page:

  • Number all the lines in a file (insert line number followed by a tab):
    :%s/^/\=line('.')."\t"/
  • Number a range of lines (from line 10 to line 20):
    :10,20s/^/\=line('.')."\t"/
  • Number a range of lines sequentially starting from 1:
    :let counter=0|10,20g//let counter=counter+1|s/^/\=counter."\t"
  • Number all the paragraphs in range starting from 1 (assuming the paragraphs are separated by one or more blank lines):
    :let counter=0|1,20g/^$\n^\s*[^\s]/let counter=counter+1|+1s/^/\=counter."\t"
    Note: The above command does not work for the first paragraph in the file if there is no blank line above it.
like image 67
Wiktor Stribiżew Avatar answered Oct 07 '22 10:10

Wiktor Stribiżew


one-shot

You can declare a variable as the other answer does, or:

:%s/^x'\([^']*\)'/\=line('.')-1/  

Replace the last 1 by the line number of your header (id, phone, name) line if it doesn't sit in line 1.

two steps

You can get followings just by replacing 1 into 0 in your codes

id  phone   name
0   12345   jack
0   45678   Jojo
0    89456  Dio
0    34872  joseph

Then you can move your cursor to the first id 0, then press:

ctrl-v G g ctrl-a

It will turn the 0s into a sequence from 1

  • ctrl-v: column mode
  • G : select the 1st col till the last line.
  • g+ctrl-a: add
like image 22
Kent Avatar answered Oct 07 '22 10:10

Kent