expr
는 괄호를 좋아하지 않는 것 같습니다 (사용 수학에서 명시적인 연산자 우선 순위) :
expr 3 * (2 + 1) bash: syntax error near unexpected token `("
bash에서 연산자 우선 순위를 표현하는 방법
답변
let
Bash 내장을 사용하는 또 다른 방법 :
$ let a="3 * (2 + 1)" $ printf "%s\n" "$a" 9
참고
@ Stéphane Chazelas가 지적했듯이 , bash
에서 ((...))
를 사용하여 expr
또는 가독성을 위해 let
.
이동성을 위해 div와 같은 $((…))
를 사용하세요. > @Bernhard 답변 .
댓글
답변
대신 산술 확장을 사용할 수 있습니다.
echo "$(( 3 * ( 2 + 1 ) ))" 9
개인적인 의견으로는 expr
를 사용하는 것보다 약간 더 멋져 보입니다.
From man bash
산술 확장 산술 확장을 사용하면 산술 표현식을 평가하고 결과를 대체 할 수 있습니다. 산술 확장의 형식은 다음과 같습니다.
$((expression))
표현식은 큰 따옴표 안에있는 것처럼 처리되지만 괄호 안의 큰 따옴표는 특별히 처리되지 않습니다. 표현식의 모든 토큰은 매개 변수 확장, 문자열 확장, 명령 대체 및 따옴표 제거를 거칩니다. 산술 확장은 중첩 될 수 있습니다.
평가는 아래 ARITHMETIC EVALUATION 아래 나열된 규칙에 따라 수행됩니다. 표현식이 유효하지 않으면 bash는 실패를 나타내는 메시지를 인쇄하고 대체가 발생하지 않습니다.
댓글
- 가독성 외에도 ' 산술을 수행하기 위해 추가 프로세스를 분기 할 필요가 없습니다. '는 셸 자체에서 처리합니다.
- POSIX 셸에서는 ' 단어에 따라 분할하므로 ' 목록 컨텍스트에서 인용하는 것이 좋은 습관입니다.
- bash 셸에서 이것을 시도하면 잘못된 변수 이름입니다. "
답변
현대 쉘에서 산술을 위해 expr
를 사용할 이유가 없습니다.
POSIX는 $((...))
를 정의합니다. 확장 연산자입니다. 따라서 모든 POSIX 호환 셸 (모든 최신 Unix 유사 셸, dash, bash, yash, mksh, zsh, posh, ksh …의 sh
)에서 사용할 수 있습니다. ).
a=$(( 3 * (2 + 1) )) a=$((3*(2+1)))
ksh
도 let
내장 기능을 도입했습니다. 같은 종류의 산술 표현식이 전달되고, “확장되지 않고”표현식이 해결되었는지 여부에 따라 종료 상태를 반환합니다. es to 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
및
.다른 쉘로의 이식성이 필요한 경우 $((...))
구문을 선호해야합니다. expr
는 POSIX 이전 Bourne 유사 쉘에만 필요합니다 (일반적으로 Bourne 쉘 또는 Almquist 쉘의 초기 버전).
Bourne이 아닌 전면에는 산술 연산자가 내장 된 몇 개의 쉘이 있습니다.
-
csh
/tcsh
(실제로 산술 평가가 내장 된 최초의 Unix 셸) :@ a = 3 * (2 + 1)
-
akanga
(rc
기준)a = $:"3 * (2 + 1)"
-
1989 년 유즈넷에 게시 된 Almquist 쉘의 원본 버전에는
expr
내장 (실제로는test
와 병합)되었지만 나중에 제거되었습니다.
댓글
- 나는 매일 새로운 것을 배우고 있습니다. St é phane. POSIX 쉘 지식에 감사드립니다!
-
: $((a = a*2))
는 어떻습니까? - 부동 소수점이 있으면 어떻게합니까? 내 표현은 a = $ ((-14 + 0.2 * (1 + 2 + 3)))입니다. 오류 토큰은 " .2 * (1 + 2 + 3) "
- @Blaise입니다. ' d zsh, ksh93 또는 yash와 같은
$((...))
에서 부동 소수점을 지원하는 쉘이 필요합니다.
Answer
expr
는 외부 명령이며 특수 셸 구문이 아닙니다. 따라서 expr
에 셸 특수 문자를 표시하려면 따옴표로 묶어 셸 구문 분석으로부터 보호해야합니다. 또한 expr
에는 각 숫자와 연산자가 별도의 매개 변수로 전달되어야합니다. 따라서 :
expr 3 \* \( 2 + 1 \)
1970 년대 또는 1980 년대의 앤티크 유닉스 시스템에서 작업하지 않는 한 . 예전에는 쉘에 산술을 수행하는 기본 제공 방법이 없었고 대신 expr
유틸리티를 호출해야했습니다. 모든 POSIX 셸에는 산술 확장 구문을 통한 산술이 내장되어 있습니다.
echo "$((3 * (2 + 1)))"
구성 $((…))
는 산술 표현식 (10 진수로 작성)의 결과로 확장됩니다. 대부분의 셸과 마찬가지로 Bash는 정수 산술 모듈로 2 64 (또는 이전 버전의 bash 및 32 비트 머신의 일부 다른 셸의 경우 모듈로 2 32 ) 만 지원합니다.
Bash는 할당을 수행하거나 표현식이 0인지 여부를 테스트하려고하지만 결과에 신경 쓰지 않는 경우 추가 편의 구문 을 제공합니다. 이 구조는 ksh 및 zsh에도 존재하지만 일반 sh에는 존재하지 않습니다.
((x = 3 * (2+1))) echo "$x" if ((x > 3)); then …
정수 산술 외에도 expr
는 몇 가지 문자열 조작 기능을 제공합니다. 이것도 POSIX 쉘의 기능에 포함됩니다. 단 하나는 예외입니다. expr STRING : REGEXP
는 문자열이 지정된 정규 표현식과 일치하는지 테스트합니다. POSIX 쉘은 외부 도구이지만 bash는 [[ STRING =~ REGEXP ]]
( 다른 regexp 구문 사용 — expr
는 고전적인 도구이며 BRE를 사용하고 bash는 ERE를 사용합니다.)
스크립트를 유지 관리하지 않는 한 20 년 된 시스템에서 실행되는 시스템이므로 expr
가 존재했음을 알 필요가 없습니다. 셸 산술을 사용합니다.
댓글
-
expr foo : '\(.\)'
는 텍스트 추출도 수행합니다.bash
'의BASH_REMATCH
도 비슷한 결과를 얻었습니다. 또한 POSIX[
가 수행하지 않는 문자열 비교도 수행합니다 (sort
를 사용하는 방법을 상상할 수 있지만). - 구문 자리 표시 자로 밑줄 — 당신은 Schemer, @Giles? :]
- @RubyTuesdayDONO ' 여기서 밑줄을 사용하지 않았습니다. U + 2026 HORIZONTAL ELLIPSIS를 잘못 읽고 있습니까? 그렇다면 더 큰 글꼴을 사용해보세요.
- @Giles — 예, 내 글꼴 크기 때문에 밑줄처럼 보입니다. 저에게 " Schemer "는 보완 요소이며 '는 줄임표와 다릅니다. 밑줄 대 밑줄은 어차피 의미를 변경합니다. 으스스 할 필요가 없습니다. : /
답변
따옴표 :
expr 3 "*" "(" 2 "+" 1 ")" 9
따옴표는 bash가 괄호를 bash 구문으로 해석하지 못하도록합니다.
댓글
- Nicolas가 설명하지만 설명하지 않는 것은
expr
명령 줄의 토큰이 공백으로 구분되어야한다는 것입니다. 그래서; 예를 들어expr 3 "*" "(2" "+" "1)"
작동하지 않습니다 . (또한 BTW, 아마도+
를 인용 할 필요가 없습니다.) - 괄호는 '
while
및[[
, 그들은 ' 구문입니다. 키워드라면 ' 명령 인수에서 그렇게 해석되지 않습니다. bash가 구문 분석하지 않고 대신 문자열 리터럴을 확인하도록 ' 따옴표가 필요합니다.
Answer
bc ..가있는 경우
echo "3 * (2 + 1)"|bc 9
let
를 사용할 이유가 없습니다. '는(( a = 3 * (2 + 1) ))
(둘 다ksh
및 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]
. 이러한 구문을 피하는 이유가 있습니까?