我希望这个问题不是重复的,因为我一直在尝试各种方法来解决这个问题,但找不到任何解决方案。
我有一个 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
答案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
删除所有\n
ewline 因为我不知道应"node$#" getbalance
该做什么,但我假设它将在其输出后添加\n
ewline,并且(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)
每次迭代执行一次是浪费的。