I need a fairly portable way of manipulating semver values in a posix environment.
Specifically:
1. sorting, and
2. incrementing one of: major, minor, patch of a given semver value.
I need a fairly portable way of manipulating semver values in a posix environment.
Specifically:
1. sorting, and
2. incrementing one of: major, minor, patch of a given semver value.
If you've got bash, I imagine you could read semver values into arrays:
File
10.4.3
11.5
124.4.5
12
You can reprint them with space padding
$ deSemverize(){ while read line; do IFS=. read -a fields<<<"$line"; printf "%4d %4d %4d\n" ${fields[@]}; done ; }
$ deSemversize < File
#=>
10 4 3
11 5 0
124 4 5
12 0 0
and since ' ' < '0'
, you can sort the result lexically and it'll be as if you sorted first by MAJOR, then MINOR and then PATCH. You can then print the results as Semver values again:
$ semverize() { while read line; do read -a fields<<<"$line"; printf "%d.%d.%d\n" ${fields[@]}; done; }
$ deSemversize < File | sort | semverize
#=> 10.4.3
11.5.0
12.0.0
124.4.5
As for modifying the fields, you can do standard bash arithmetics on numerical variables with (())
or $(())
, e.g.:
echo "$((fields[0]+1))"
I would use a right-aligned Mask:
semverBump() {
local mask=$1
local dots_in_mask=${mask//[^.]/}
case "$dots_in_mask" in
"") mask=..$mask;;
".") mask=.$mask;;
esac
local maskarray
IFS=. read -a maskarray<<<"$mask"
while read line;
do IFS=. read -a fields<<<"$line";
for((i=0;i<3;i++))
do
((fields[$i]+=0))
[[ -z "${maskarray[$i]}" ]] && continue
if [[ "${maskarray[$i]}" =~ ^[+-].* ]]; then
((fields[$i]+=maskarray[$i]))
else
((fields[$i]=maskarray[$i]))
fi
done
printf "%d.%d.%d\n" ${fields[@]}
done ;
}
E.g.:
semverBump +2 < File #increase all minor by 2
semverBump 2 < File #set all minor to two
semverBump +1.-1.0 < File #increment major, decrement minor, set patch to zero