The trick for splitting up the version blurb for just the version number, is to pass the values you want in before the command, and then shift them off $@
.
you have done a relatively unfamiliar-to-me parsing mechanism with the resetting the field separators, etc. Using bash as a parser is a problem for me (and I've never hated myself enough to try....).
I would set up a function that takes a co-ordinate of a version as a line/word combination, and rely on out-of-bash tools to do it......
I will probably get nailed for starting 4 sub-processes, but head, tail, and cut are small.... right? (Forgive me already, you won't be calling this in a tight loop, will you? You're already doing that a bit with the bash $( ...)
operator...)
get_version_number() {
local line=$1
shift
local word=$1
shift
# echo Line $line Word $word and Commend $@
# set local variable to executed arguments that is passed in
echo "$( $@ | head -$line | tail -1 | cut -d ' ' -f $word)"
}
Then you would call it like:
gitver=$(get_version_number 1 3 git --version)
perlver=$(get_version_number 2 4 perl -version)
echo Git and Perl are $gitver and $perlver respectively
which for me, produces:
Git and Perl are 1.7.1 and v5.10.1 respectively
This also allows you to do things like get the redhat version as
rhelver=$(get_version_number 1 7 cat /etc/issue)
javaver=$(get_version_number 1 3 java -version)
and even things like the current time 23:45:08
;-)
time=$(get_version_number 1 4 date)
Some notes:
- historically, it is 'expensive' to start lots of child processes. It still is a problem, but not quite as bad as it was. Doing that hundreds or thousands of times may add up to seconds of time wasted. If you can avoid creating child processes, do it.... but, sometimes it's just easier to be lazy than to be super-bash-smart.
- I create an additional 4 processes (actually 5) each time you call the function. One for the
$( ... )
, one for the $@
inside that, one for head
, one for tail
, and one for cut
. That is almost excessive.... but if you are calling this 100 times, then it's OK, if you are calling it 1000 times, you will be able to save seconds by doing it differently.
- the
$( ... )
operator is formally called the Command Substitution. What it means is that everything inside the structure is run as if in a 'child' bash process.... (so a new process is created, and the output is substituted in place of the command)
- what the
shift
operator does is take $@ and remove the first item.... so, your function called as get_version_number 1 3 git --version
gets 4 parameters, 1
, 3
, git
and --version
. We copy $1
off as $line
, and then shift $@, so there are now only 3 parameters in $@
. We then copy $1
again (but because of the shift, it is a different value) as $word
, and then shift again to remove it. We are left with just git
and --version
as the parameters.
If you wanted, for example, to save one process each time, you could instead do:
get_version_number() {
local line=$1
shift
local word=$1
shift
GOTVERSION="$( $@ | head -$line | tail -1 | cut -d ' ' -f $word)"
}
get_version_number 1 3 java -version
javaversion=$GOTVERSION
That saves using the $( .... )
and echo
combination, so you save a process, but the code is a bit more complicated.
Edit 2.
'Obviously', what I suggest you do is not necessarily the best thing. Your code was working fine, and the mechanism will be faster (slightly) than mine because it does not do the additional 4 processes and keeps the logic inside bash internal commands.
Here is my 'shift' system applied to your code:
get_version_number() {
local word=$1
shift
# set local variable to executed arguments that is passed in
local command="$($@)"
# set up temp variable and assign to global IFS variable
OIFS=$IFS
# set up IFS to split the string on empty space
IFS=" "
# read commands output into an array and store it in $array variable
read -a array <<< "$command"
# clear out IFS back to what it original was for further use
IFS=$OIFS
# echo out array at a particular indices that should be passed in
echo ${array[$word]}
}
and you would call it with the word-number for the version as the first argument:
gitver=$(get_version_number 3 git --version)
But this does not allow you to find versions on multi-line outputs.....