답변:
letbash 내장 을 사용하는 다른 방법 :
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
노트
따라 @ 스테판 Chazelas가 지적 에, bash당신이 사용해야 ((...))이상의 연산을 수행 expr하거나 let가독성을 위해.
이식성을 위해 @Bernhard answer$((...)) 와 같이 사용하십시오 .
let. (( a = 3 * (2 + 1) ))( kshksh, bash 및 zsh에서 제공되며 ksh, bash 및 zsh에서만 사용 가능) 보다 표준 또는 휴대용이 아니며 읽기 어렵거나 인용하기가 쉽지 않습니다. a=$((3 * (2 + 1)))휴대용으로 사용하십시오 .
((a = 3 * (2 + 1) )), 이식성에 대한 대안 a=$((3 * (2 + 1)))). 따라서 당신이나 당신의 대답에 대한 메모가 아니라 선택된 대답에 반대합니다. 그리고 최고 득점자.
a=1 $[a+2]또는을 사용했다 a=1 b=2 $[a+b]. 그 구문을 피해야하는 이유입니까?
대신 산술 확장을 사용할 수 있습니다.
echo "$(( 3 * ( 2 + 1 ) ))"
9
내 개인적인 견해로는을 사용하는 것보다 조금 더 좋아 보입니다 expr.
에서 man bash
산술 확장 산술 확장을 통해 산술 표현식을 평가하고 결과를 대체 할 수 있습니다. 산술 확장 형식은 다음과 같습니다.
$((expression))표현식은 큰 따옴표 안에있는 것처럼 처리되지만 괄호 안의 큰 따옴표는 특별히 처리되지 않습니다. 표현식의 모든 토큰은 매개 변수 확장, 문자열 확장, 명령 대체 및 따옴표 제거를 거칩니다. 산술 확장이 중첩 될 수 있습니다.
평가는 산술 평가 아래에 나열된 규칙에 따라 수행됩니다. expression이 유효하지 않으면 bash는 실패를 나타내는 메시지를 인쇄하고 대체가 발생하지 않습니다.
expr현대 쉘에서 산술에 사용할 이유가 없습니다 .
POSIX는 $((...))확장 연산자를 정의합니다 . 따라서 모든 POSIX 호환 쉘 ( sh모든 현대 유닉스 계열, 대시, bash, yash, mksh, zsh, posh, ksh ...)에서 사용할 수 있습니다.
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
ksh또한 let같은 종류의 산술 표현식이 전달되고 무언가로 확장되지 않고 표현식이 0으로 해석되는지 여부에 따라 종료 상태를 반환 하는 내장 기능을 도입 했습니다 expr.
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi
그러나 인용문이 어색하고 이해하기 쉽지 않기 때문에 ( expr물론 같은 정도는 아님) 대체 형식 ksh도 도입했습니다 ((...)).
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))
훨씬 더 읽기 쉬우 며 대신 사용해야합니다.
let및 ((...))에서만 사용할 수 있습니다 ksh, zsh그리고 bash. $((...))다른 쉘로의 이식성이 필요한 경우 , 구문은 exprPOSIX 이전 Bourne 유사 쉘 (일반적으로 Bourne 쉘 또는 Almquist 쉘의 초기 버전)에만 필요합니다.
Bourne이 아닌 프론트에는 내장 된 산술 연산자가있는 몇 개의 쉘이 있습니다.
csh/ tcsh(실제로 산술 평가 기능이 내장 된 최초의 유닉스 쉘) :
@ a = 3 * (2 + 1)akanga(기준 rc)
a = $:'3 * (2 + 1)'1989 년에 유즈넷에 게시 된 Almquist 쉘의 원래 버전은 기본적으로 expr내장되어 test있었지만 (실제로 병합 됨 ) 나중에 제거되었습니다.
: $((a = a*2))?
$((...))zsh, ksh93 또는 yash와 같은 부동 소수점을 지원하는 셸이 필요합니다 .
expr외부 명령이며 특수 쉘 구문이 아닙니다. 따라서 expr쉘 특수 문자를 보려면 인용 부호를 사용하여 쉘 구문 분석으로부터 보호해야합니다. 또한 expr각 숫자와 연산자를 별도의 매개 변수로 전달해야합니다. 그러므로:
expr 3 \* \( 2 + 1 \)
1970 년대 또는 1980 년대의 골동품 유닉스 시스템을 사용하지 않는 한, 사용할 이유가 거의 없습니다 expr. 예전에는 셸에 산술을 수행하는 기본 제공 방법이 없었으므로 expr대신 유틸리티 를 호출해야 했습니다. 모든 POSIX 쉘에는 산술 확장 구문을 통해 내장 된 산술이 있습니다.
echo "$((3 * (2 + 1)))"
구조 $((…))는 산술 연산 결과 (10 진수로 표시됨)로 확장됩니다. 대부분의 셸과 마찬가지로 Bash는 정수 산술 모듈로 2 64 (또는 이전 버전의 bash 및 32 비트 시스템의 다른 셸의 경우 모듈로 2 32) 만 지원합니다 .
배시는 할당을 수행하거나 표현식이 0인지 여부를 테스트하지만 결과에 신경 쓰지 않을 때 추가 편의 구문을 제공합니다 . 이 구조는 ksh와 zsh에도 존재하지만 일반 sh에는 존재하지 않습니다.
((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then …
정수 산술 외에도 expr몇 가지 문자열 조작 기능을 제공합니다. 이것들도 POSIX 쉘의 기능에 의해 제외되고, 하나를 제외하고 : expr STRING : REGEXP문자열이 지정된 정규 표현식과 일치하는지 테스트합니다. 는 POSIX 쉘은 외부 도구없이이 작업을 수행 할 수 있지만, bash는 함께 할 수 [[ STRING =~ REGEXP ]]의 (a와 다른 정규 표현식 구문 - expr고전적인 도구입니다 BRE를 사용 배쉬는 ERE를 사용합니다).
20 년 된 시스템에서 실행되는 스크립트를 유지 관리하지 않는 한 기존 스크립트를 알 필요는 없습니다 expr. 쉘 산술을 사용하십시오.
expr foo : '\(.\)'텍스트 추출도 수행합니다. bash의는 BASH_REMATCH비슷한을 달성한다. 또한 POSIX [가하지 않는 문자열 비교를 수행합니다 (물론 사용 방법을 상상할 수 sort는 있음).
따옴표와 함께 괄호를 사용하십시오.
expr 3 '*' '(' 2 '+' 1 ')'
9
따옴표는 bash가 괄호를 bash 구문으로 해석하지 못하게합니다.
expr명령 행 의 토큰 이 공백으로 분리되어야한다는 것입니다. 그래서; 예를 들어 expr 3 "*" "(2" "+" "1)" 작동하지 않습니다 . (또한 BTW, 당신은 아마 인용 할 필요가 없습니다 +.)
whileand와 같은 키워드가 아니며 [[구문입니다. 키워드 인 경우 명령 인수에서 해석되지 않습니다. bash가 구문 분석하지 않고 대신 문자열 리터럴을 볼 수 있도록 따옴표가 필요합니다.