在循环中分配变量标识符并回显其值

在循环中分配变量标识符并回显其值

我希望这个问题不是重复的,因为我一直在尝试各种方法来解决这个问题,但找不到任何解决方案。

我有一个 for 循环,在其中我想将命令输出存储到一个变量中,该变量的名称每轮都会更改,并且希望对这些变量进行 echo 和进一步操作,如下所示:

for i in `seq 1 $netsize`
do
    echo "node$i: "
    export Bal$i=$(node$i getbalance | bc)  #PIPE TO BC SINCE getbalance RETURNS FLOAT TYPE VALUE
    echo $Bal$i | tee -a <text-file path>   #THIS GIVES ME ONLY 1,2,... NOT THE getbalance VALUE!!!
...

此外,我想获取 node1 的 getbalance 并将其除以所有节点的总余额之和。所以我这样做了,但出现了语法错误:

...
echo "$Bal1/($Bal1+$Bal2+$Bal3+$Bal4+$Bal5+$Bal6+$Bal7+$Bal8+$Bal9)" | bc >> <text-file path> #HERE; I DO THIS FOR A netsize OF 9 NODES ...

对于任意网络大小,我该如何解决第二个问题?

答案1

您可以使用 bash 数组来完成此操作。我会将这些值保存到索引数组中,如下所示:

declare -a bal
for i in `seq 1 $netsize`
do
    echo "node$i: "
    bal[$i]=$(node$i getbalance | bc) //PIPE TO BC SINCE getbalance RETURNS FLOAT TYPE VALUE

    echo ${bal[$i]} # should be the right value
done

然后将您想要回显的命令放在一起,bc我们将使用子 shell 等玩一个小IFS游戏

denominator=$(IFS=+; echo "${bal[*]:2}")
equation="${bal[1]}/($denominator)"

设置IFS=+将使数组中的字段在+我们在下一条语句中回显它们时分隔开。访问数组${bal[*]:2}的所有元素bal(即${bal[*]}部分)。但在这种情况下,我们知道元素号 1 是我们想要跳过的元素,因为我们将在方程的分子中使用它,所以我们添加:2从索引开始的元素2。因此我们得到了数组索引 2 及以上${bal[*]:2}的所有元素。bal

您可以查看有关 bash 数组切片的更多信息在这些答案中或者更多这里

答案2

netsize=$somenum
(   echo  scale=\(2;  set --                           ### set scale; clear args
    while [ "$#" -lt "$netsize" ]                      ### counts up to $netsize
    do    set "$@" "bal$(($#+1))"                      ### saves arg count as bal$#+1
    ###   I do the below because you don't say what 
    ###   node$# getbalance does. Here it's random.
          eval "node$#(){ "':& x=${!%??} y=${!#"$x"}
                               echo "$x.$y/'"$#\"; }"  ### fakes a node$#() function
          printf "%bbal$#=%b" ');"' '";' \(            ### );"bal$#=";(bal$#=
          "node$#" getbalance                          ### $x.$y/$#\n
    done; printf %b+ ");($1/($@))\c"                   ### );(bal1/(bal1+...bal$netsize))
) | paste -sd\\0 | bc                                  ### removes all \newlines but last

因此,要说出你想要做什么并不容易,但我注意到一件事,你似乎认为你需要bc为每个算术评估调用一个单独的函数。相反的是迄今为止更方便的方法 -bc是一个交互式程序,而且它本身就是一种成熟的脚本语言。它将在其正常运行时间内设置和存储变量值 - 因此,与其尝试将所有这些信息存储在 shell 中,只需输出方程并bc为您存储它们的值即可。

例如:

{ echo 'x=1+2'; echo '"x=";x'; }| bc

...打印...

x=3

因为首先bc计算结果x为 equal 1+2,然后它将任意字符串打印"x="到 stdout ,最后它被要求打印x的值,所以它就这样做了。

上面的脚本实际上做了同样的事情。每次迭代bal都会加一。它打印出来bc

);"bal$#=";(bal$#=$!/$#\n

...然后当它递增$#以匹配$netsize它时打印(以10为例$netsize...

(bal1/(bal1+bal2+bal3+bal4+bal5+bal6+bal7+bal8+bal9+bal10))

这些值根本没有保存在 shell 中 -bc但会记住它们。当您将bc表达式括在(括号中时),它将被计算打印。

我用来paste -sd\\0删除所有\newline 因为我不知道应"node$#" getbalance该做什么,但我假设它将在其输出后添加\newline,并且(bal1=node$# getbalance's output\n)是一个语法错误。所以我将它们全部清除并用;分号分隔表达式(我宁愿希望不是一个字符node$# getbalance会打印)。要清楚地了解整个脚本打印的内容,您可以将bc尾部的 替换为 w/ tr \; \\n

例如,如果满足以下条件,它将打印netsize=10

scale=(2)
"bal1="
(bal1=261.40/1)
"bal2="
(bal2=261.41/2)
"bal3="
(bal3=261.42/3)
"bal4="
(bal4=261.44/4)
"bal5="
(bal5=261.45/5)
"bal6="
(bal6=261.46/6)
"bal7="
(bal7=261.48/7)
"bal8="
(bal8=261.49/8)
"bal9="
(bal9=261.52/9)
"bal10="
(bal10=261.54/10)
(bal1/(bal1+bal2+bal3+bal4+bal5+bal6+bal7+bal8+bal9+bal10))

所有这些都经过bc打印,如下所示:

bal1=261.40
bal2=130.70
bal3=87.14
bal4=65.36
bal5=52.29
bal6=43.57
bal7=37.35
bal8=32.68
bal9=29.05
bal10=26.15
.34

如果您可以更清楚地了解您的输入和输出,我可以帮助您更具体地根据您的需求进行定制 - 但var=$(echo stuff at | bc)每次迭代执行一次是浪费的。

相关内容