저는 Bash 3을 사용하고 있으며 조건부를 형성하십시오. C / C ++에서는 아주 간단합니다 : ((A || B) && C)
. Bash에서는 그렇지 않습니다 (Git 작성자가 다른 작업으로 이동하기 전에이 코드를 제공했을 것입니다).
이것은 작동하지 않습니다. <0 or 1>
는 문자열 리터럴이 아닙니다. 0 또는 1을 의미합니다 (일반적으로 grep -i
에서 가져옴).
A=<0 or 1> B=<0 or 1> C=<0 or 1> if [ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eqe "0" ]; then ... fi
결과 :
line 322: syntax error near unexpected token `[["
그런 다음 시도 :
A=<0 or 1> B=<0 or 1> C=<0 or 1> if [ ([ "$A" -eq "0" ]) || ([ "$B" -ne "0" ]) ] && [ "$C" -eq "0" ]; then ... fi
결과 :
line 322: syntax error near unexpected token `[["
문제의 일부는 검색 결과가 사소한 예이며 복합 조건이있는 더 복잡한 예가 아니라는 것입니다.
간단한
Bash에서?
그냥 펴서 여러 블록에서 동일한 명령을 반복 할 준비가되었습니다.
A=<0 or 1> B=<0 or 1> C=<0 or 1> if [ "$A" -eq "0" ] && [ "$C" -eq "0" ]; then ... elif [ "$B" -ne "0" ] && [ "$C" -eq "0" ]; then ... fi
Answer
bash의 구문은 C에서 영감을받은 일부라도 C와 비슷하지 않습니다. 단순히 C 코드를 작성하고 작동 할 것으로 기대할 수는 없습니다.
쉘의 핵심은 명령을 실행하는 것입니다. 대괄호 열기 명령 [
은 단일 테스트를 수행하는 명령입니다 ¹. 마지막 닫는 대괄호없이 test
로 쓸 수도 있습니다. ||
및 &&
연산자는 셸 연산자이며 테스트가 아닌 명령 을 결합합니다.
그래서
[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ]
그것이 다음과 같이 파싱 될 때
[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ]
다음과 같습니다.
test [ "$A" -eq "0" || test "$B" -ne "0" ] && test "$C" -eq "0"
불균형 괄호에 주목하십니까? 예, 좋지 않습니다. 괄호를 사용한 시도는 동일한 문제가 있습니다. 가짜 대괄호
명령어를 그룹화하는 구문은 중괄호입니다. 중괄호가 구문 분석되는 방식은 그 앞에 완전한 명령이 필요하므로 “중괄호 안의 명령을 줄 바꿈 또는 세미콜론으로 종료해야합니다.
if { [ "$A" -eq "0" ] || [ "$B" -ne "0" ]; } && [ "$C" -eq "0" ]; then …
거기 “이중 대괄호를 사용하는 다른 방법입니다. 단일 대괄호와 달리 이중 대괄호는 특수 쉘 구문입니다. 조건식 을 구분합니다. 이중 괄호 안에는 &&
및 ||
와 같은 괄호와 연산자를 사용할 수 있습니다. 이중 괄호는 셸 구문이므로 셸은 이러한 연산자가 괄호 안에있을 때 “일반 셸 명령 구문의 일부가 아니라 조건식 구문의 일부임을 알고 있습니다.
if [[ ($A -eq 0 || $B -ne 0) && $C -eq 0 ]]; then …
모든 테스트가 숫자 인 경우 관절 식 을 구분하는 또 다른 방법이 있습니다. 산술 표현식은 C와 유사한 구문으로 정수 계산을 수행합니다.
if (((A == 0 || B != 0) && C == 0)); then …
내 bash 대괄호를 찾을 수 있습니다. 입문서 가 유용합니다.
[
는 일반 sh에서 사용할 수 있습니다. [[
및 ((
는 bash (및 ksh 및 zsh)에만 해당됩니다.
¹ 또한 가능합니다. 여러 테스트를 부울 연산자와 결합하지만 사용하기가 번거롭고 미묘한 함정이 있으므로 설명하지 않겠습니다.
댓글
답변
[[
사용 :
if [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]; then ...
[
를 선호하는 경우 다음이 작동합니다.
if [ \( "$A" -eq "0" -o "$B" -ne "0" \) -a "$C" -eq "0" ]; then ...
댓글
- 감사합니다, Stephen. 제 경우에는 첫 번째 예제를 사용했습니다 … regex = ' ^ [0-9] + $ ' length = $ {#datearg} if! [[$ datearg = ~ $ regex & & $ length -eq 8]]; then echo " 오류 : 8의 길이가 아닙니다 "; fi
Answer
대신 -o
연산자를 사용하세요. 중첩 ||. 필요한 경우 -a
를 사용하여 & &를 대체 할 수도 있습니다. .
EXPRESSION1 -a EXPRESSION2 both EXPRESSION1 and EXPRESSION2 are true EXPRESSION1 -o EXPRESSION2 either EXPRESSION1 or EXPRESSION2 is true if [ "$A" -eq "0" -o "$B" -ne "0" ] && [ "$C" -eq "0" ]; then echo success;fi
댓글
- 감사합니다.
-a
및-o
를 발견했지만 실험하지는 않았습니다. Stack Overflow의 누군가가 그것을 피하라고 말했습니다. 나는 스크립트를 사용하면 스크립트를 읽을 수 없기 때문에 대부분 동의했습니다. - …하지만 이식성이 더 뛰어납니다.
- @Kusalananda-이식성에 대한 경고에 감사드립니다. 스크립트는 Bash 2부터 Bash 4까지의 시스템에서 실행되어야합니다.
[[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]
에 문제가 있습니까? -
bash
또는[[ ... ]]
를 이해하는 다른 셸 - -a 사용의 단점은 ' 첫 번째 표현이 거짓이면 단락하지 않습니다. 따라서 잠재적 인 치명적인 두 번째 표현식이 실행되는 것을 방지하기 위해 단락에 의존하는 경우 -a를 사용할 수 없습니다. 예 : pastebin.com/zM77TXW1
[[ … ]]
가 추가되었습니다. bash 2.02에서.((…))
가 bash 2.0에 추가되었습니다.||
및[
에서[[
및((
로 변경합니다.[
의 우선 순위 와 같지만 (평가 순서를 제어하려면 괄호 사용) & &는[[
및((
에서(C에서와 같음)
[[ … ]]
또는$((…))
는 그룹화 전용입니다.