Reputation: 739
I am new to bash and writing a script that needs to compare the minor version of the kernel to see if it is greater than or equal to 10, and exit if it is not. Currently I have something like this:
KERNEL=$(uname -r)
declare -i MINOR_VERSION=$(echo $KERNEL | cut -c 3-4)
if [ "10" -gt "$MINOR_VERSION"]; then exit 0; fi
This is bad code, and doesn't work if the minor version is < 10 since I am using cut and depending on it being two digits. What I probably need is something that parses the minor version by using the dots. Example:
$ uname -r
3.4.0-60-generic
$ MNR_VAR=<awesome bash code, with cut or sed or something>
$ echo $MNR_VAR
4
I have been reading cut
and sed
documentation but have just been slow picking it up. I would appreciate the help!
TL;DR - looking for a bash command that will extract an int
surrounded by the first two dots in a variable. "3.13.0.x" returns '13', "3.2.0.x" returns '2', etc.
EDIT: Some answers as one liners below for those curious.
uname -r | cut -d '.' -f2
uname -r | awk -F . '{print $2}'
kernel="$(uname -r)" | tmp="${kernel#*.}" | minor="${tmp%%.*}" | echo "$minor"
Upvotes: 2
Views: 3751
Reputation: 20970
Extracting just minor version & comparing it with something is risky, because major number can change too...
I normally prefer padding the numbers with zeros, so that they can be easily compared using simple string compare.
kernel_version=$(uname -r | sed -r 's/([0-9]+)/0000\1/g; s/0*([0-9]{4})/\1/g') # gives 0003.0004.0000-0060-generic
if [[ "$kernel_version" < "0003.0010" ]]; then exit 0; fi
Upvotes: -1
Reputation: 22428
In pure bash:
#!/bin/bash
ker="$(uname -r)"
minker="${ker#*.}"
minker="${minker%%.*}"
echo "$minker"
"${ker#*.}"
is the string after the first match of a .
in $ker
. Thus
$minker
becomes 13.0-generic...
from 3.13.0-generic...
"${minker%%.*}"
is the string left by cutting all matches (from right) of .
and whatever after it, in $minker
. Thus $minker
becomes 13
from 13.0-generic...
See the Bash Parameter Expansion Manual for more info
Using Bash Regex:
#!/bin/bash
regex='([0-9]+)\.([0-9]+)'
[[ $(uname -r) =~ $regex ]]
echo ${BASH_REMATCH[2]}
Upvotes: 4
Reputation: 80921
The problem is you are using -c
to cut
. Don't do that.
Use the -f
and -d
flags instead to control the delimiter and fields to output.
Or use awk -F . '{print $2}' <<< "$(uname -r)"
.
Or use IFS=. read -r _ minor _rest <<< "$(uname -r)"; echo "$minor"
(which has the benefit of not using any external utilities).
The usage of <<< "$(uname -r)"
is bash-specific (I believe) but avoids the need for a pipe (|
) and the sub-shell that it involves.
Upvotes: 2