5

I've never work with shell (bash), but found some bug in script, that I used to increment version. Script works fine, until this case

version=1.27.9
echo $version | awk -F. -v OFS=. 'NF==1{print ++$NF}; NF>1{if(length($NF+1)>length($NF))$(NF-1)++; $NF=sprintf("%0*d", length($NF), ($NF+1)%(10^length($NF))); print}'

1.28.0  <-- result, but I need 1.27.10

In this case new_version will be equals to 1.28.0. How to change this script to avoid incrementing MINOR number? For this case I expecting 1.27.10

I've no experience in shell, so don't know where to start. I found this script here, on SO and use it. Please help me to solve my problem. Thank you in advance.

RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
Я TChebur
  • 366
  • 6
  • 23

2 Answers2

8

EDIT: To change only MINOR version try following.

echo "$version" | awk 'BEGIN{FS=OFS="."} {$3+=1} 1'

Explanation: Adding explanation to above code.

echo "$version" |           ##using echo to print variable version value here and passing it to awk program.
awk '                       ##Starting awk program from here.
BEGIN{                      ##Starting BEGIN section of this awk program here.
  FS=OFS="."                ##Setting FS and OFS as dot(.) here for all lines of Input_file.
}
{
  $3+=1                     ##For every line of Input_file adding 1 to 3rd field and saving output to $3 itself.
}
1                           ##Mentioning 1 will print edited/non-edited lines here.
'


Could you please try following, to change middle version as per last(minor) version which OP confirmed not needed but which I understood at very first glance of this requirement.

echo "$version" | awk 'BEGIN{FS=OFS="."} {$3+=1;if($3>9){$2+=1;$3=0}} 1'
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
7

A pure Bash solution:

#!/usr/bin/env bash

version='1.27.9'

# Read Semver fields
IFS=. read -r major minor patch <<<"$version"

# Increment patch version
# same as patch="$((patch + 1))"
((patch++))

# Re-assemble version string from Semver fields
printf -v version '%d.%d.%d' "$major" "$minor" "$((patch))"
  • IFS=.; Sets the field separator to . in the local scope of the read command.
  • read -r major minor patch <<<"$version": Reads Semver fields from the "$version here-string.
  • ((patch++)): Increments the $patch version using Bash's stand-alone arithmetic. (Can be replaced by patch="$((patch + 1))")
  • printf -v version '%d.%d.%d' "$major" "$minor" "$((patch))": Formats the $version string with updated fields, using Bash's printf -v variable (output to variable) feature.

A short-hand one-line equivalent to @RavinderSingh13 's version:

IFS=. read -r a b c<<<"$version";echo "$a.$b.$((c+1))"

Or a POSIX one-liner:

OIFS="$IFS";IFS=.;set -- $version;echo "$1.$2.$((10#$3+1))";IFS="$OIFS";set --
  • OIFS="$IFS": Saves the Internal Field Separator.
  • IFS=.: Set the dot as Field Separator.
  • set -- $version: Splits the version string into arguments, using the IFS.
  • echo "$1.$2.$((10#$3+1))": Prints the upgraded minor Semver 10#$3 with specifying base 10 for 3rd argument.
  • IFS="$OIFS": Restores the IFS to its original value.
  • set --: Clears the arguments array.
Léa Gris
  • 17,497
  • 4
  • 32
  • 41