이 명령에 대해 {}가 작동하지 않는 이유는 무엇인가요?

이 명령에 대해 {}가 작동하지 않는 이유는 무엇인가요?

.{}()
아래 코드 조각에서:

#!/bin/bash
set -e
echo "two">file.txt
ARRAY=(one two three)
rc=0
for i in ${ARRAY[@]}; do
    echo "grepping $i "
    #grep "$i" file.txt || (echo "failed grep" && exit 1) <--1
    #grep "$i" file.txt || {rc=$? && echo "failed grep"}  <--2
    grep "$i" file.txt || (rc=$? && echo "failed grep")   <--3
done

exit $rc  

명령 2는 작동하지 않는 유일한 명령입니다. 그러나 나는 그것이 작동할 것이라고 예상했고 명령 1은 허용된 답변에 따라 스크립트를 종료하지 않습니다.여기
무슨 일인지 설명해 줄 수 있는 사람이 있나요?

답변1

bash대부분의 POSIX 셸 에서 while (및 는 셸 구문의 특수 표시 문자입니다( , , , , ... )와 같은 다중 문자 표시의 일부를 포함하여 발생할 때마다 특별히 처리됩니다 ) . 조합은 in과 같은 특수 표시 문자를 사용 하거나 특수 또는 양식에 사용됩니다.(($(<($((<#(({}${{x,y}{x..y}

echo )while 은 오류가 발생 하지만 echo }출력이 없으므로 in 을 닫는 것이 불가능하다는 것을 알 수 있습니다 .}}{echo}{

구체적 으로 {}핵심 단어좋다 while, time, !. 명령이 필요한 경우에만(첫 번째 근사치에서) 별도의 단어로만 나타날 수 있습니다.

{echo뒤에 오는 키워드 {echo가 아니라 명령이 됩니다 . 키워드 다음에 it 이 오는 대신 명령 과 같습니다 .{echowhile[while[while[

및 가 분리되어 명령 위치에 있는 경우 또는 를 사용할 수 있지만 은 사용할 수 없습니다 { echo;}.{<file cat;}{}{echo}

그러나 몇 가지 예외가 있습니다. 일반적으로 리디렉션 외에는 아무 일도 일어나지 않고 명령 위치에 없는 {(echo test)}닫힌 후에도 이 작업이 작동한다는 것을 알 수 있습니다 . 지휘 위치에 있지 않은 두 번째 사람 도 마찬가지입니다.)}{ { echo; } }}

{ echo; ! }또는 { echo; time }ksh93에서는 작동하지만 작동하지 않습니다 ( 명령 위치에 bash있더라도 ).}

한 가지 예외는 가능한 경우 및 를 토큰으로 인식 zsh하려고 시도하는 것 입니다 . 즉, 지휘 위치에 있고 특정 제한된 상황에 있을 때입니다. 거기에서는 작동하지만 예를 들어 작동하지는 않습니다 . bash/ksh 대신 거기 처럼요 .{}{echo}{{echo}}{{echo} }{echo,foo}{ echo,foo;}echo foo

<file {head;head}작동 zsh하지만 다른 쉘에서는 작동하지 않습니다.

이는 IGNORE_BRACES및 옵션에 의해 IGNORE_CLOSE_BRACES제어 됩니다.

답변2

콜론 으로 {}구분된 형식 복합 명령문의 자리 표시자 이며 변수 업데이트가 중괄호 외부에 반영되지 않는 하위 쉘 컨텍스트를 만듭니다.bash()

$?grep또는 다른 쉘 명령을 사용할 때 반환 코드 값을 망칠 필요조차 없습니다. 0콘솔 출력을 억제하여 if 조건에서 직접 종료 코드를 사용할 수 있습니다 (일반적으로 성공하면 명령을 반환함). 플래그를 grep활성화하면 -q이 작업을 수행 할 수 있습니다.

if grep -q "$i" file.txt; then
    printf "grep suceeded\n"
else
    printf "grep failed\n"
fi

종료 코드를 수동으로 저장하려면 복합 문을 사용하는 것이 맞습니다(여기서는 서브쉘 사용이 작동하지 않습니다!). 복합문을 다음과 같이 끝내면 됩니다.;

grep "$i" file.txt || {rc=$? ; echo "failed grep" ; }

이제 종료 코드를 사용할 수 있습니다 rc. 또는 더 간단하게는 echo 자체에서 변수를 사용할 수 있습니다.

grep "$i" file.txt || echo "failed grep with rc: $?"

sub-shell을 사용하여 답변에 추가하려면 ()변수 컨텍스트를 저장하는 것이 좋습니다.아니요좋은 습관입니다. 연결된 명령이 완료된 직후 셸이 종료됩니다.

예를 들어 다음과 같은 간단한 문자열 동일성 연산을 사용하세요.

str='foo'; rc=0
[[ $str == *doo* ]] || { rc=$?; echo "string comparison failed" ; }
echo "$rc"

값을 올바르게 반영 rc하지만 서브쉘의 경우 작동하지 않습니다.

str='foo'; rc=0
[[ $str == *doo* ]] || ( rc=$?; echo "string comparison failed" )
echo "$rc"

서브쉘 내에서 0설정할 때 반환되어야 하는 값을 반영합니다.1


[실제 문제와 관련 없음]

항상 배열 확장을 인용해야 합니다. 그렇게 하지 않으면 공백이나 기타 특수 문자가 포함된 배열 요소를 하나의 단어로 처리하지 않고 별도의 단어로 분할합니다.

for i in "${ARRAY[@]}"; do

관련 정보