Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I bump a version number using bash

Tags:

bash

replace

I would like to know how to bump the last digit in a version number using bash.

e.g.

VERSION=1.9.0.9
NEXT_VERSION=1.9.0.10

EDIT: The version number will only contain natural numbers.

Can the solution be generic to handle any number of parts in a version number.

e.g.

1.2
1.2.3
1.2.3.4
1.2.3.4.5
like image 730
froogz3301 Avatar asked Dec 19 '10 22:12

froogz3301


People also ask

How to increment version number in a shell script?

bash - How to increment version number in a shell script? - Stack Overflow How to increment version number in a shell script? The following simple version control script is meant to find the last version number of a given file, increment it, run a given command with the newly created file (e.g., editor), and after that save it to stable.

How do I find the last version number of a file?

The following simple version control script is meant to find the last version number of a given file, increment it, run a given command with the newly created file (e.g., editor), and after that save it to stable. Since it's simple, it doesn't check anything since the script would be modified as needed.

Is there a way to compare Python version numbers?

Because only compiled Python can be called by you would think a binary exists to do this or its possible in shell. Instead of comparing version numbers, you could test directly for the feature itself. declare -A returns 2 (at least in Bash 3.2) if it doesn't recognize -A, so test for that (it also prints an error):

How do you increment a variable in Bash?

1 . The most simple way to increment/decrement a variable is by using the + and - operators. ... 2 The += and -= Operators #. In addition to the basic operators explained above, bash also provides the assignment operators += and -=. 3 Using the ++ and -- Operators #. ... 4 Conclusion #. ...


3 Answers

TL;DR:

VERSION=1.9.0.9
echo $VERSION | awk -F. '/[0-9]+\./{$NF++;print}' OFS=.
# will print 1.9.0.10

For a detailed explanation, read on.


Let's start with the basic answer by froogz3301:

VERSIONS="
1.2.3.4.4
1.2.3.4.5.6.7.7
1.9.9
1.9.0.9
"

for VERSION in $VERSIONS; do 
    echo $VERSION | awk -F. '{$NF = $NF + 1;} 1' | sed 's/ /./g'
done

How can we improve on this? Here are a bunch of ideas extracted from the copious set of comments.

The trailing '1' in the program is crucial to its operation, but it is not the most explicit way of doing things. The odd '1' at the end is a boolean value that is true, and therefore matches every line and triggers the default action (since there is no action inside braces after it) which is to print $0, the line read, as amended by the previous command.

Hence, why not this awk command, which obviates the sed command?

awk -F. '{$NF+=1; OFS="."; print $0}'

Of course, we could refine things further — in several stages. You could use the bash '<<<' string redirection operator to avoid the pipe:

awk -F. '...' <<< $VERSION

The next observation would be that given a series of lines, a single execution of awk could handle them all:

echo "$VERSIONS" | awk -F. '/[0-9]+\./{$NF+=1;OFS=".";print}'

without the for loop. The double quotes around "$VERSION" preserve the newlines in the string. The pipe is still unnecessary, leading to:

awk -F. '/[0-9]+\./{$NF+=1;OFS=".";print}' <<< "$VERSIONS"

The regex ignores the blank lines in $VERSION by only processing lines that contain a digit followed by a dot. Of course, setting OFS in each line is a tad clumsy, and '+=1' can be abbreviated '++', so you could use:

awk -F. '/[0-9]+\./{$NF++;print}' OFS=. <<< "$VERSIONS"

(or you could include 'BEGIN{OFS="."}' in the program, but that is rather verbose.

The '<<<' notation is only supported by Bash and not by Korn, Bourne or other POSIX shells (except as a non-standard extension parallelling the Bash notation). The AWK program is going to be supported by any version of awk you are likely to be able to lay hands on (but the variable assignment on the command line was not supported by old UNIX 7th Edition AWK).

like image 191
2 revs Avatar answered Oct 19 '22 20:10

2 revs


I have come up with this.

VERSIONS="
1.2.3.4.4
1.2.3.4.5.6.7.7
1.9.9
1.9.0.9
"

for VERSION in $VERSIONS; do 
    echo $VERSION | awk -F. '{$NF = $NF + 1;} 1' | sed 's/ /./g'
done
like image 9
froogz3301 Avatar answered Oct 19 '22 22:10

froogz3301


if [[ "$VERSION" == *.* ]]; then
    majorpart="${VERSION%.*}."
else
    majorpart=""
fi
minorpart="${VERSION##*.}"
NEXT_VERSION="$majorpart$((minorpart+1))"

Warning: if the minor part of the version number isn't in the expected format (integer, no leading zeros), this may have trouble. Some examples: "1.033" -> "1.28" (since 033 is octal for 27), "1.2.b" -> "1.2.1" (unless b is a defined variable, it'll be treated as 0), "1.2.3a" -> error ("3a" isn't a number). Depending on how many cases you want to cover, this can be made arbitrarily complex.

like image 3
Gordon Davisson Avatar answered Oct 19 '22 20:10

Gordon Davisson