expr 산술의 괄호 : 3 * (2 + 1)

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.

이동성을 위해 $((…))를 사용하세요. > @Bernhard 답변 .

댓글

  • +1 훨씬 더 읽기 쉽습니다! 동료 Linux 사용자에게 도움이 될 것이라고 생각하여 질문 + 답변을 게시했지만 이제는 다른 답변에서 많은 이점을 얻고 있습니다. 🙂
  • 저기 '는 let를 사용할 이유가 없습니다. '는 (( a = 3 * (2 + 1) )) (둘 다 ksh 및 ksh, bash 및 zsh에서만 사용할 수 있습니다). '는 읽기 어렵거나 인용하기 쉽습니다. a=$((3 * (2 + 1)))를 사용하여 휴대 할 수 있습니다.
  • ' 말하지 않습니다. ' 틀 렸습니다. ' 더 나은 대안 (가독성을위한 것 ((a = 3 * (2 + 1) )), 이식성 a=$((3 * (2 + 1)))), 따라서 ' 귀 하나 귀하의 답변에 대한 메모가 아니라 선택한 답변 및 최고 득점자에 대한 메모입니다. .
  • @St é phaneChazelas : 답변이 업데이트되었습니다!
  • 저는 항상 a=1 $[a+2] 또는 a=1 b=2 $[a+b]. 이러한 구문을 피하는 이유가 있습니까?

답변

대신 산술 확장을 사용할 수 있습니다.

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))) 

kshlet 내장 기능을 도입했습니다. 같은 종류의 산술 표현식이 전달되고, “확장되지 않고”표현식이 해결되었는지 여부에 따라 종료 상태를 반환합니다. 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 

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다