j0nr
j0nr

Reputation: 301

Add Padded Incremental Number to End of Each Line in VIM

I have a text file with a list in it:

dateformatfile.ext
dateformatfile.ext
dateformatfile.ext
...

I need to add a padded number to the end of each, like so:

dateformatfile.ext 00001
dateformatfile.ext 00002
dateformatfile.ext 00003
...

There are a lot, so I need to have a command to do this somehow.

Thanks in advance.

Upvotes: 3

Views: 4687

Answers (6)

Anonymous Cowherd
Anonymous Cowherd

Reputation: 361

If you have PERL in your environment, you can run a PERL one-liner inside your VIM session.

:%! perl -pe " $count++ ; s/$/$count/"

The caveat is that you might have to use double quotes around your perl script. On my PC, PERL will run if I use single quotes. But I cannot address variables with the dollar sign.

Upvotes: 0

cutemachine
cutemachine

Reputation: 6250

Here is my take.

Position cursor on first line where you want to add the first number.
:let i=0 Define a variable to hold the count.
qm Start to record a macro into register m.
A <C-R>=printf("%05d", i)<CR><ESC> Add a space and the ouput from printf.
:let i+=1 Increment the count for the next macro execution.
q End the recording of the macro.

jVG Visual select the rest of the document where we want to add numbers.
:normal @m Execute the macro to add the numbers to the selected lines.

I think this approach has some advantages:

  • No ugly escaping necessary.
  • The count is not tied to the line number. Allowing for offsets.
  • Using a macro can be easily combined with the :global command. For example:

:g/ext$/ normal @m Execute macro stored in register m on lines ending in ext.

Upvotes: 4

Kent
Kent

Reputation: 195209

if your text block is sitting at the beginning of the file. which means the line you want to append "00001" is the first line of your file, try this command, I just simply check the line ending with ext, you could change it to right regex if it is needed:

:%s/ext$/\="ext  ".printf("%05d", line("."))/g

if the text block is not at the beginning of the file. You just check the first line (the line you want to append 00001) of the block and get the line number, for example, line number 5:

:let b=5|%s/ext$/\="ext  ".printf("%05d", line(".")-b+1)/g

Upvotes: 2

lbonn
lbonn

Reputation: 2599

I would do this using macros (I like macros :D).

First, let's take care of the numbers (we'll pad them later). Add manually the number 1 at the end of the first line. Then record this macro on the first line :

qq        - record the macro q
$         - go at the end of the line
F<space>  - go backward to the last space
"ay$      - copy till the end of the line in the buffer a
j$        - go at the end of the line below
"ap       - copy the buffer content
<ctrl+A>  - increment the number
q         - stop recording the macro

Now you can apply it a bunch of times with 1000@q (it will stop at the end of the file).

This is not really pretty but it does the job.

For the padding, I would use another ugly trick. First, use a regex to match 3 digits numbers and add a 0 before, then do the same with 2 digits numbers (add two 0 this time) and so on...

vim macros are pretty ugly but they are useful to me when I am too tired to write a oneliner (I should learn awk though). Also, they can help you remember some obscure, yet useful vim shortcuts.

Upvotes: 0

hd1
hd1

Reputation: 34677

One could very easily do this using awk. The NR variable gives you the record number, and records map to lines unless the RS variable is redefined. So the following:

awk -e '{ print $0 NR }' filename should do the trick. Padding them is an exercise left up to the reader.

Upvotes: 0

Matthew Strawbridge
Matthew Strawbridge

Reputation: 20640

Assuming you want to do this for every line in your file, you can use the line number like this:

:execute "% normal A \<C-R>=printf(\"%05d\", line(\".\"))\<CR>"

where

  • execute(...) runs the string as a command
  • % normal runs a normal command on every line of the file
  • A appends to the line
  • <C-R>= inserts the result of a command
  • printf("%05d", ...) formats the second parameters as a five-digit number
  • line(".") gets the number of the current line
  • <CR> completes the <C-R>= insertion

Upvotes: 11

Related Questions