stack
stack

Reputation: 841

How to make the number result to a string with value in it

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

Answers (2)

Shawn
Shawn

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

nhatnq
nhatnq

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

Related Questions