Reputation: 841
I want to get some number, and assign the result to a custom string。I want to get numbers and I can use it in the next part of this script
the name of this cript is calQue.sh. the content of it is like:
#!/bin/bash
lsfDir=/opt/ibm/lsf/10.1/linux3.10-glibc2.17-x86_64/bin
Queue="ser short medium large"
for i in $Queue
do
queName=`echo $i"idleNum"`
$queName"idleNum"=`$lsfDir/bhosts hg_$i | grep ok | awk '{if($5==0) print $0}' | wc -l`
done
echo $seridleNum
I ran it,
sh calQue.sh
and it is wrong. the result i got is:
calQue.sh: line 14: seridleNumidleNum=1: command not found
calQue.sh: line 14: shortidleNumidleNum=7: command not found
calQue.sh: line 14: mediumidleNumidleNum=37: command not found
calQue.sh: line 14: largeidleNumidleNum=4: command not found
So i tried other ways like:
for i in $Queue
do
queName=`echo $i`
idleNum=`$lsfDir/bhosts hg_$i | grep ok | awk '{if($5==0) print $0}' | wc -l`
#`echo $i`Num=$idleNum //it is wrong
#$queName=$idleNum //it is wrong
done
and
Queue="ser short medium large"
for i in $Queue
do
queName=`echo $i`
"$i"idleNum=`$lsfDir/bhosts hg_$i | grep ok | awk '{if($5==0) print $0}' | wc -l`
echo $"$i"idleNum //it is wrong
done
How do i can get correct result, for example:
string seridleNumidleNum should be equal 1;
I find it is right when the string without variable $i
idleNum=`$lsfDir/bhosts hg_$i | grep ok | awk '{if($5==0) print $0}' | wc -l`
echo $idleNum
Upvotes: 0
Views: 129
Reputation: 52589
Since you're using bash
, a better approach than trying to generate variable names at runtime is to use an associative array to store values. For example:
#!/bin/bash
lsfDir=/opt/ibm/lsf/10.1/linux3.10-glibc2.17-x86_64/bin
# Make idleNum an associative array
declare -A idleNum
# Note using a regular array here instead of a single string that relies on
# shell word splitting
Queue=(ser short medium large)
for i in "${Queue[@]}"
do
# No need to use grep or wc here; awk can do it all.
idleNum[$i]=$("$lsfDir/bhosts" "hg_$i" | awk '/ok/ && $5==0 { c++ } END { print c+0 }')
done
printf "%s\n" "${idleNum[ser]}"
If you can't use associative arrays for some reason (Like being stuck on an ancient version of bash
), declare
is better than eval
for building a variable name, as it avoids a bunch of potential issues with evaluating an arbitrary string:
declare "${i}idleNum=$("$lsfDir/bhosts" "hg_$i" | awk '/ok/ && $5==0 { c++ } END { print c+0 }')"
To get the value of a variable with a name that is constructed at runtime, you can use indirect expansion:
i=ser
name="${i}idleNum"
printf "%s\n" "${!name}"
See also Why is $(...)
preferred over backticks? from the bash FAQ.
On a related note, it's a good idea to run scripts through https://www.shellcheck.net/ to find many potential issues.
Upvotes: 0
Reputation: 1193
If I understand correctly, you want to store the result to a variable which has the name as the string value e.g seridleNumidleNum. By default the shell will execute the command which definitely leads to the not found issue. A correct way is to put it into eval
command
eval $queName"idleNum"=`$lsfDir/bhosts hg_$i | grep ok | awk '{if($5==0) print $0}' | wc -l`
((expression))
can be used as an alternative
((expression)) The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1
Upvotes: 1