- 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어
명령어: echo
키워드: 산술식, 산술 확장, 산술 평가
사용처: expr 명령어를 사용하지 않고 산술식을 계산한 결과를 얻고 싶을 때
실행예제
$ ./bash-arithmetic.sh
1.txt에서 100.txt 까지 100개의 파일이 작성됨
스크립트
#!/bin/bash
# 브레이스 확장으로 1에서 100까지 숫자 목록 생성
for i in {1..100} #---------------------------- 1
do
# 산술 확장을 이용해서 파일명에 3을 곱해서 계산한
# 값을 텍스트 파일에 저장
echo $((i * 3)) > ${i}.txt #----------------- 2
done
해설
이 스크립트는 1에서 100가지의 파일명을 가진 파일을 작성합니다. 파일 내용은 파일명 숫자에 3을 곱한 값입니다. 어떤 테스트 파일을 대량으로 만들고 싶을 때 사용하면 유용합니다.
우선 1
에서 브레이스 확장을 이용해서 1에서 100까지 숫자 목록을 만듭니다.
2
에서 bash 고유 기능인 산술 확장(Arithmetic Expansion)을 이용합니다. 이 방법은 $((산술식))
이라고 하는데, 괄호 안 산술식을 계산해서 그 결과를 숫자로 확장하는 표기법입니다. 이 산술식은 변수명 앞에 있는 $ 기호를 생략할 수 있습니다. 산술 확장은 일반적으로 sh 셸 스크립트에서 expr 명령어로 계산한 부분을 치환하는 목적으로 이용됩니다.
산술 확장에서 자주 사용하는 연산자는 다음과 같습니다. 자바나 C 언어에서 이용하는 연산자와 거의 같으므로 어렵지 않을 것입니다.
연산자 | 설명 |
---|---|
+ | 덧셈 |
- | 뺄셈 |
* | 곱셈 |
/ | 나눗셈(버림) |
% | 나머지 |
** | 제곱 |
« | 왼쪽 쉬프트(비트 연산) |
» | 오른쪽 쉬프트(비트 연산) |
산술 확장은 expr 명령어와는 달리 외부 명령어를 이용하지 않고 게산하여 속도가 무척 빠릅니다. 또한 변수명에 $가 필요 없으므로 곱셈 연산자 *를 이스케이프하지 않아도 되어 작성하기 편리합니다.
-
expr 명령어와 산술 확장의 차이점
result=$(expr $i \* $i) <-- expr 명령어는 곱셈 기호에 이스케이프 필요 result=$((i * i)) <-- 산술 확장은 $과 이스케이프 불필요
그리고 산술 확장과 비슷한 예로 산술 평가(Arithmetic Evaluation)가 있습니다. 이것은 산술식을 평가해서 그 참과 거짓을 돌려줍니다. 따라서 if문이나 while문 조건식으로 test 명령어 대신에 사용하는 경우가 많습니다. 또한 증감/차감 연산자는 대입 연산 없이 단독으로도 사용할 수 있습니다. 연산 결과를 돌려주지 않아서 산술 확장보다는 산술 평가로 이용하는 것이 일반적입니다. 다음은 산술 평가를 이용해서 while 반복문을 작성하는 예입니다. expr 명령어를 사용하지 않으니 셸 스크립트 특유의 번잡함이 줄어드는 걸 알 수 있습니다.
-
파일1
산술 평가를 사용하는 반복 처리#!/bin/bash # i=1에서 9까지 while 반복 처리 i=1 while ((i < 10)) do 어떤 처리 ((i++)) done
이렇듯 bash 산술 확장, 산술 평가를 이용하면 다양한 수치 계산을 간단히 작성할 수 있습니다. 또한 expr 명령어 오버헤드도 없어져서 스크립트가 빨라지는 것도 기대할 수 있습니다.
주의사항
-
산술 확장은 변수 앞 $ 기호를 생략할 수 있는데 예외적으로 인수를 나타내는 위치 파라미터($1, $2 등)만 $ 기호를 생략하면 예를 들어 $1은 1이 되어서 숫자와 구분이 가지 않기 때문입니다.
-
산술 평가에는 let 명령어를 이용하는 방법이 있습니다. 다음처럼 let 명령어 인수에 산술을 넘기면 산술 평가 표기법(())과 마찬가지로 산술식이 실행되어서 참/거짓 값이 돌아옵니다. 다음 두 줄은 같은 의미입니다.
((i++)) let 'i++'
-
셸 변수를 declare문 -i 옵션으로 정의하면 대상 변수는 $(()) 표기법을 사용하지 않아도 산술 확장을 이용할 수 있습니다.