How to split a version number and assign each number to a variable?

Viewed 104

I want to be able to extract the individual numbers from a version string and assign each value to a variable.

echo -en "Please Enter A "$RPM_FILTER" Version Number (e.g. "$VER_EXAMPLE"):"

I want to be able to assign for example 1 to $a, 16 to $b and 0 to $c for use in a sed filter.

Specify Version Number (y/n)? y
Please Enter A Version Number (e.g. 1.16.0): 1.16.0
read -p " " VERSION

I am using this currently but this does not work when the individual version number is two digits.

declare -i a=$(printf "%s\n" "$VERSION" | cut -c 1)
declare -i b=$(printf "%s\n" "$VERSION" | cut -c 3)
declare -i c=$(printf "%s\n" "$VERSION" | cut -c 5)
3 Answers

You can separate the values in VERSION simply by changing the value for IFS (Internal Field Separator). Make sure you save the old value (default space, tab, newline) and restore IFS after you read. Set the new value for IFS to '.' so bash word-splits on '.' for your read, e.g.

#!/bin/bash

printf "Please Enter A Version Number (e.g. 1.16.0): "
oldifs="$IFS"
IFS=$'.'
read a b c
IFS="$oldifs"

printf "%s %s %s\n" $a $b $c

(note: setting IFS can be done as part of the read line which avoids having to save the old IFS value and restore it when done, e.g. IFS=$'.' read a b c)

Example Use/Output

$ bash myscript.sh
Please Enter A Version Number (e.g. 1.16.0): 1.16.0
1 16 0

You can use awk for this since your common separator is a ..

Eg:

a=$(echo "$VERSION" | awk -F'.' '{print $1}'
b=$(echo "$VERSION" | awk -F'.' '{print $2}'
c=$(echo "$VERSION" | awk -F'.' '{print $3}'

I typically find that awk syntax to be the most straightforward, but I understand wanting to use cut. You're pretty close on your syntax, but you just need to specify a delimiter using -d.

Eg:

a=$(echo "$VERSION" | cut -d'.' -f1)
...

Assuming OP may want to maintain the input in its original form we can eliminate the half dozen subprocesses (3x awk/cut) with a single IFS/read/here-string combo:

VERSION='1.16.0'                          # result of OP's 'read -p " " VERSION'
IFS=. read -r a b c <<< "${VERSION}"

NOTE: in this case the IFS change is limited to the scope of the read call (ie, no need to save/set/reset IFS)

The results:

$ typeset -p a b c
declare -- a="1"
declare -- b="16"
declare -- c="0"
Related