Bash 스크립트에서 숫자를 어떻게 추가 할 수 있습니까?


566

이 Bash 스크립트가 있고 16 행에서 문제가있었습니다. 15 행의 이전 결과를 가져 와서 16 행의 변수에 추가하려면 어떻게해야합니까?

#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do
    for j in `ls output-$i-*`; do
        echo "$j"

        metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
        num= $num + $metab   (line16)
    done
    echo "$num"
 done

2
다음 답변을 사용해도 0 값을 인쇄한다고 생각합니다. "내부 번호"의 최종 값을 "외부 번호"로 가져 오는 트릭 (예 : 프로세스 섭씨)이 있습니다.
Scott Chu

답변:


974

정수의 경우 :

  • 산술 확장 사용 :$((EXPR))

    num=$((num1 + num2))
    num=$(($num1 + $num2))       # Also works
    num=$((num1 + 2 + 3))        # ...
    num=$[num1+num2]             # Old, deprecated arithmetic expression syntax
  • 외부 expr유틸리티 사용 이것은 실제로 오래된 시스템에만 필요합니다.

    num=`expr $num1 + $num2`     # Whitespace for expr is important

부동 소수점의 경우 :

Bash는 이것을 직접 지원하지 않지만 사용할 수있는 몇 가지 외부 도구가 있습니다.

num=$(awk "BEGIN {print $num1+$num2; exit}")
num=$(python -c "print $num1+$num2")
num=$(perl -e "print $num1+$num2")
num=$(echo $num1 + $num2 | bc)   # Whitespace for echo is important

과학적 표기법 (예 :)을 사용할 수도 있습니다 2.5e+2.


일반적인 함정 :

  • 변수를 설정할 때의 양쪽에 공백을 넣을 수 없습니다 =. 그렇지 않으면 쉘이 첫 번째 단어를 실행할 응용 프로그램의 이름으로 해석합니다 (예 : num=또는 num)

    num= 1 num =2

  • bc그리고 expr공백이 중요하므로, 별도의 인수로 각 숫자와 연산자를 기대합니다. 와 같은 인수를 처리 할 수 ​​없습니다 3+ +4.

    num=`expr $num1+ $num2`


1
첫 번째 답변에서는 expr : non-numeric argument를 출력합니다. 두 번째는 작동하지 않습니다.
Nick

1
@ Nick : 변수 이름 num1num2존재하고 정수 값을 갖는 동안 이것을 시도 했습니까 ?
sorpigal

1
그러나 그들은 존재하지만 하나의 변수는 두 배입니다.
Nick

2
그래, 그건 문제 야 :) 참고 : $((..))산술 평가는 bash에서 실행됩니다. expr별도의 프로세스로 실행되므로 속도가 훨씬 느려집니다. arithemtic 평가가 지원되지 않는 시스템에서 후자를 사용하십시오 (sh! = bash)
Karoly Horvath

4
$((…))POSIX에 의해 표준화 되었기 때문에 , 점점 더 expr필요한 것은 드물어 질 것 입니다.
chepner

115

$(( ))산술 확장을 사용하십시오 .

num=$(( $num + $metab ))

자세한 내용은 13 장. 산술 확장 을 참조하십시오.


2
이상한. 계산하려고 할 때 여기에서 작동하지 않습니다 191.003 + 190.
Sigur

2
소수점이있는 숫자에는 작동하지 않습니다.
fivedogit

30

그것을하는 방법은 수천 가지가 있습니다. 다음 dc은 무제한 정밀 산술을 지원하는 리버스 데스크 계산기입니다.

dc <<<"$num1 $num2 + p"

그러나 그것이 당신을 위해 너무 bash-y (또는 이식성 문제)라면 말할 수 있습니다.

echo $num1 $num2 + p | dc

그러나 아마도 당신은 RPN이 불안정하고 이상하다고 생각하는 사람들 중 하나 일 것입니다. 걱정 마세요! bc당신을 위해 여기 있습니다 :

bc <<< "$num1 + $num2"
echo $num1 + $num2 | bc

즉, 스크립트와 관련하여 몇 가지 관련이없는 개선 사항이 있습니다.

#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do
    for j in output-$i-* ; do # 'for' can glob directly, no need to ls
            echo "$j"

             # 'grep' can read files, no need to use 'cat'
            metab=$(grep EndBuffer "$j" | awk '{sum+=$2} END { print sum/120}')
            num=$(( $num + $metab ))
    done
    echo "$num"
done

Bash FAQ 022에 설명 된대로 Bash는 기본적으로 부동 소수점 숫자를 지원하지 않습니다. 부동 소수점 숫자를 합산해야하는 경우 외부 도구 ( bc또는 같은 dc)를 사용해야합니다.

이 경우 해결책은

num=$(dc <<<"$num $metab + p")

부동 소수 점수를에 추가 num합니다.


1
@ Soorpigal Thankssss 많은 .. 내가 당신에게 다른 것을 요청할 수 있습니까?
Nick

23

bash에서

 num=5
 x=6
 (( num += x ))
 echo $num   # ==> 11

bash는 정수 산술 만 처리 할 수 ​​있으므로 awk 명령이 분수를 반환하면 다시 디자인해야합니다. awk에서 모든 수학을 수행하기 위해 코드를 약간 다시 작성했습니다.

num=0
for ((i=1; i<=2; i++)); do      
    for j in output-$i-*; do
        echo "$j"
        num=$(
           awk -v n="$num" '
               /EndBuffer/ {sum += $2}
               END {print n + (sum/120)}
           ' "$j"
        )
    done
    echo "$num"
done

20

나는 항상 문법을 잊어 버려서 구글에 왔지만, 내가 익숙한 것을 찾지 못했습니다 : P. 이것은 나에게 가장 깨끗하고 다른 언어로 기대하는 것에 더 맞습니다.

i=0
((i++))

echo $i;


15

나는이 방법도 좋아하고 덜 혼란 스럽습니다.

count=$[count+1]

1
그런데 왜 이것이 작동합니까? 우리는 이것을 어떻게 부릅니까? 이것에 관한 문서를 찾을 수 없습니다.
skyline75489

4
덜 혼란 스럽지만 더 이상 사용되지 않습니다.
Camille Goudeseune


7

POSIX에서 수행 bash할 수있는 또 다른 휴대용 호환 방법으로 , .bashrc편의의 모든 산술 연산자를위한 함수로 정의 할 수 있습니다 .

addNumbers () {
    local IFS='+'
    printf "%s\n" "$(( $* ))"
}

명령 줄에서 다음과 같이 호출하면됩니다.

addNumbers 1 2 3 4 5 100
115

아이디어는 확장 후 단어 분할 에 사용되는 특수 변수 인 입력 필드 구분 기호 (IFS)bash사용하고 행을 단어로 분할하는 것입니다. 이 함수는 단어 분리 문자를 합계 연산자로 사용하도록 값을 로컬로 변경합니다 +.

(가) 기억 IFS로컬로 변경되고 않습니다 NOT 기본에 효과가 걸릴 IFS기능 범위 이외의 동작을. man bash페이지 에서 발췌

쉘은 IFS의 각 문자를 분리 문자로 취급하고 다른 확장 결과를이 문자의 단어로 나눕니다. IFS가 설정되지 않았거나 해당 값이 정확히이면 기본값, 시퀀스,, 및 이전 확장 결과의 시작 및 끝에서 무시되고 시작 또는 끝이 아닌 IFS 문자 시퀀스가 ​​구분됩니다. 말.

"$(( $* ))"나누기 위해 전달 된 인수 목록을 나타내고 +나중에 합계 값이 printf함수를 사용하여 출력 됩니다. 다른 산술 연산을위한 범위를 추가하기 위해이 기능을 확장 할 수 있습니다.


2
#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do      
    for j in `ls output-$i-*`; do
        echo "$j"

        metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
        let num=num+metab (line 16)
    done
    echo "$num"
done

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.