0

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
stack
  • 821
  • 1
  • 15
  • 28
  • `bhosts` isn't standard POSIX shell, it looks like an IBM related command, e.g. [bhosts](https://www.ibm.com/docs/en/spectrum-lsf/10.1.0?topic=reference-bhosts). Have you consulted that documentation? – David C. Rankin Jul 14 '21 at 03:14
  • @DavidC.Rankin, it is nothing about bhosts, see my update. – stack Jul 14 '21 at 03:21
  • 1
    Can you post the actual script? `"calQue.sh: line 14:"` -- what you posted only has 13 lines so we are missing something... That appears to be the result of `$queName"idleNum"=\`$lsfDir/bhosts hg_$i ...` -- which obviously won't be found. – David C. Rankin Jul 14 '21 at 03:42

2 Answers2

1

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

nhatnq
  • 1,173
  • 7
  • 16
0

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.

Shawn
  • 47,241
  • 3
  • 26
  • 60