Becoming a wizard with Vim
Tags: vim, nvim, regex
Published: 2020-11-24 22:36:24

---
title: Becoming a wizard with Vim
published: true
description: Using advanced vim commands to tranform numbers
tags: vim, nvim, regex
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/d577typo1o2kumf3ivye.jpg
---

# The problem:
+ source: https://stackoverflow.com/questions/64961886

I have a block in a yaml file that I would like to yank and paste several times:

    - probeNumber: 1
      probeLocation: [0, 0, 0.1]
      

Is it possible to automatically increment the value of probeNumber and probeLocation in each block? Like so:

    - probeNumber: 1
      probeLocation: [0, 0, 0.1]
    
    - probeNumber: 2
      probeLocation: [0, 0, 0.15]
    
    - probeNumber: 3
      probeLocation: [0, 0, 0.20]

probeLocation is not an integer, it is incremented by a fixed value in each block (0.05). I need 1000 or so of these blocks so doing this manually is not feasible.
      
## fast and magic solution (creating the file):

Just select the 3 first lines (we need at least one blank line between each block), copy to the clipboard and run:

    :for i in range(999) | silent! 0put + | endfor
    
## The second problem
Now increasing the numbers to fit your needs

In order to increase `probeNumber` lines:

    :let c=1 | g/\d\+$/ s//\=c/ | let c+=1

Now the lines with `probeLocation`:

    :let c=0.10 | g/0\.1\ze]/ s//\=printf("%0.2f", c)/ | let c+=0.05

In the above global commands we are  using a counter `c=1`  and increasing it. At the substitution part we are usig an expression register `\=something`. On the `printf` function we are converting the counter to a float point number with two digits. On each line of the global pattern we are also increasing the counter by `0.05`.

## Substitute spaces for dashes but not on entire line:

Supose you have these lines and want to remove spaces only i the name of the files

```txt
cp 01-file with spaces.txt $HOME/tmp/01-file with spaces.txt
cp 02-file with spaces.txt $HOME/tmp/02-file with spaces.txt
```

One regex to match only the filenames could be:

```sh
/\d\+-[^.]*
```

The solution the will be:

```sh
%s/\d\+-[^.]*/\=substitute(submatch(0), ' ', '-', 'g')/g
```

Or if you have something like:

```txt
Time in hours, minutes and seconds which I want to substrat 00:04:01
Time in hours, minutes and seconds which I want to substrat 00:05:01
Time in hours, minutes and seconds which I want to substrat 00:06:12
Time in hours, minutes and seconds which I want to substrat 00:14:01
Time in hours, minutes and seconds which I want to substrat 00:00:01
```
And you want to decrease 10 seconds in every match:

```sh
:%s/00.*\ze$/\=system('date -u -d "'.submatch(0).' +0000 -10 sec" +"%H:%M:%S"')/g
```

I have created a script called **less2sec** that uses the date command above and have a default second decrease '02' and a default hour, just to give the user an example. Take a look on the script:

```sh
#!/bin/env bash
# Bash script to decrease [defaut 02] sec
# Last Change: Tue, 31 May 2022 15:52
# vim: ft=sh

# Note: I had to remove the clear command because it
# puts some trash on my final output I use on vim
# https://unix.stackexchange.com/a/564986/3157

HELP(){
        cat <<-EOF
                  HELP
        -------------------------------
        Subtract seconds from HH:MM:SS"
        -------------------------------
        ${0##*/} [-h] [hora] [segundos]

EOF
}

[ "$1" == "-h" ] && HELP && exit 1

[ "$1" ] && hora="$1"  || hora="11:17:00"
[ "$2" ] && param="$2" || param="02"

# echo -e "\t${0##*/} Script para subtrair segundos"
# echo -e "\tImprimindo $hora menos $param segundos:"
hora=$(date  -u -d"$hora +0000 -$param sec" '+%H:%M:%S')

# here we are using "printf" to avoid  the new line character
printf "%s" "$hora"
```

We have to add a space after the script name and befor the amount of seconds we want to decrease.

```vim
:%s/.*/\=system('less2sec ' . submatch(0) . ' 10')
```

The only catch is that your regex, the search part, must match a column of text like this: `00:01:00`.

## Give me some feedback, some insight to improve this article or correct any possible mistake.