How to increment the last number in a string; bash

Updated Answer

Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:

perl -spe 's/(\d+)(?!.*\d+)/$1>$thresh? $1+1 : $1/e' <<<  "abc123_456.txt" -- -thresh=500

Original Answer

You can evaluate/calculate a replacement with /e in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:

perl -pe 's/(\d+)(?!.*\d+)/$1+1/e' <<< "abc123_456.txt"
abc123_457.txt

The (?!.*\d+) is (hopefully) a negative look-ahead for any more digits.

The $1 represents any sequence of digits captured in the capture group (\d+).

Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.


Using bash regular expression matching:

$ f="/foo/bar/baz59_ 99stuff.thing"
$ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]

OK, what do we have now?

$ declare -p BASH_REMATCH
declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")

So we can construct the new filename

if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
    prefix=${f%${BASH_REMATCH[0]}}           # remove "99stuff.thing" from $f
    number=$(( 10#${BASH_REMATCH[1]} + 1 ))  # use "10#" to force base10
    new=${prefix}${number}${BASH_REMATCH[2]}
    echo $new
fi
# => /foo/bar/baz59_ 100stuff.thing

With GNU awk for the 3rd arg to match():

$ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 6stuff.thing

Just set t to whatever your threshold value is for incrementing, e.g.:

$ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 5stuff.thing

Tags:

Bash

Perl

Awk

Sed