루프에 변수 식별자를 할당하고 해당 값을 에코합니다.

루프에 변수 식별자를 할당하고 해당 값을 에코합니다.

이 문제를 해결하기 위해 다양한 방법을 시도했지만 해결책을 찾을 수 없기 때문에 이 질문이 중복되지 않기를 바랍니다.

매 라운드마다 이름이 변경되는 변수에 명령 출력을 저장하고 에코하고 다음과 같이 이러한 변수에 대해 추가로 작업하려는 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 ...

임의의 네트워크 크기에 대한 두 번째 문제를 어떻게 해결합니까?

답변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)반복할 때마다 한 번만 수행하는 것은 낭비입니다.

관련 정보