Becoming a wizard with Vim

Sérgio Araújo - Nov 24 '20 - - Dev Community

The problem:

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]
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Now the lines with probeLocation:

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

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

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
Enter fullscreen mode Exit fullscreen mode

One regex to match only the filenames could be:

/\d\+-[^.]*
Enter fullscreen mode Exit fullscreen mode

The solution the will be:

%s/\d\+-[^.]*/\=substitute(submatch(0), ' ', '-', 'g')/g
Enter fullscreen mode Exit fullscreen mode

Or if you have something like:

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
Enter fullscreen mode Exit fullscreen mode

And you want to decrease 10 seconds in every match:

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

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:

#!/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"
Enter fullscreen mode Exit fullscreen mode

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

:%s/.*/\=system('less2sec ' . submatch(0) . ' 10')
Enter fullscreen mode Exit fullscreen mode

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .