ループに変数識別子を割り当て、その値をエコーし​​ます。

ループに変数識別子を割り当て、その値をエコーし​​ます。

この問題を解決するためにさまざまな方法を試しましたが、解決策が見つからないため、この質問が重複しないことを願っています。

各ラウンドごとに名前が変更された変数にコマンド出力を保存してエコーし、これらの変数に対して次のようにさらに作業したいforループがあります。

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 ...

任意のネットワークサイズに関する2番目の問題をどのように解決しますか?

答え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サブシェルなどを使って小さなIFSゲームをすることになります。

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

設定すると、次のステートメントでそのフィールドをエコーすると、配列内のIFS=+フィールドが分​​離されます。配列のすべての要素(たとえば、一部)に+アクセスします。ただし、この場合、要素番号1が方程式の分子に使用されるため、スキップしたい要素であることがわかっているので、indexから始まる要素を追加します。したがって、配列インデックス2以上ですべての要素が取得されます。${bal[*]:2}bal${bal[*]}:22${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それ自体が完全なスクリプト言語である対話型プログラムです。通常の実行時間中に変数の値を設定して保存するので、これらすべての情報をシェルに保存するのではなく、方程式を出力してそのbc値を保存します。

たとえば、

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

...印刷...

x=3

最初に同等とbc評価してから、ランダムな文字列をstdoutに印刷し、最後に値を印刷するように求められます。x1+2"x="x

上記のスクリプトは実際に同じことを行います。各反復はbal1ずつ増加します。それは印刷されますbc

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

...そして$#一致するように増加すると$netsize印刷されます。(10を例に挙げます$netsize。)...

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

この値はシェルにまったく保存されませんが、bc記憶されます。bc式を(括弧で囲むと)評価されます。そして印刷。

私はそれが何をすべきかわからないので、paste -sd\\0すべてのewlineを削除しようとしましたが、出力の後にewlineが追加されると仮定します。\n"node$#" getbalance\n(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)繰り返すたびに一度だけ行うことは無駄です。

関連情報