복합 명령에서 bash 옵션 설정

복합 명령에서 bash 옵션 설정

extglob복합 복합 내에서 쉘 옵션을 설정하면 이후의 glob 확장이 실패하는 것으로 나타났습니다 . 복합 명령 외부에서 셸 옵션을 설정해야 합니까? Bash 매뉴얼 페이지에는 그러한 요구 사항이 없습니다.

예를 들어 다음 스크립트는 제대로 작동합니다(인쇄 a.0 a.1).

#!/bin/bash
touch a.0   a.1 \
      a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)

그러나 마지막 두 줄을 복합 명령으로 실행하면 다음 오류와 함께 스크립트가 실패합니다.

syntax error near unexpected token `('
`    ls "a."!(b*)'

이는 Bash 버전 4.2 ~ 4.4 및 다양한 버전을 사용하고 있습니다.복합 명령:

(1) 조건부—if

#!/bin/bash
touch a.0   a.1 \
      a.b.0 a.b.1
if true; then
    shopt -s extglob
    ls "a."!(b*)
fi

(2) 교정기 -{ }

#!/bin/bash
touch a.0   a.1 \
      a.b.0 a.b.1
{
    shopt -s extglob
    ls "a."!(b*)
}

(3) 서브쉘-- ( ):

#!/bin/bash
touch a.0   a.1 \
      a.b.0 a.b.1
(
    shopt -s extglob
    ls "a."!(b*)
)

모든 경우에 shopt복합 명령 외부로 이동하면 스크립트가 성공합니다.

답변1

전체 명령이 구문 분석될 때까지 복합 명령의 어떤 부분도 실행되지 않습니다. 이는 간접적으로 문서화되어 있습니다.쉘 작업매뉴얼에서: 모든 토큰화 및 구문 분석은 "the" 명령이 실행되기 전에 발생합니다. extglob토큰화 중에 인식되는 새로운 패턴 일치 연산자를 추가하여 언어 구문을 변경할 수 있습니다 .

명령이 도착했을 때 아직 실행되지 않았기 때문에 shopt단일 항목으로 처리되지 않고(히스토리 확장이 없을 뿐이라는 등) 히스토리 확장( )이나 제어 연산자를 시도한 것으로 처리됩니다.!(!(!(@(

두 경우 모두 구문 분석이 이 표시에 도달하면 일반적으로 오류가 발생합니다. 비록 !(...)줄의 시작 부분이거나 time음수 서브쉘 파이프 뒤에 있더라도 마찬가지입니다. " unexpected token `('"는 해당 위치에서 하위 쉘 표현식을 허용할 수 없음을 의미합니다.

서브셸에서 일시적으로 extglob을 활성화하려는 경우에는 약간 성가신 일입니다. 한 가지 해결 방법은 필수 glob을 사용하는 함수를 정의한 다음 extglob을 다시 비활성화한 다음그 다음에extglob이 활성화된 서브셸에서 이 함수를 호출하세요.

shopt -s extglob
f() { ls "a."!(b*) ; }
shopt -u extglob
(
    shopt -s extglob
    f
)

매우 부피가 큽니다.


구문 분석되기 전에 처리되기 때문에 복합 명령 내에서 별칭을 생성하는 경우에도 동일한 효과가 발생합니다.

if true
then
    alias foo=echo
    foo bar
fi
foo xyz

별칭 때문에 을 인쇄 foo: command not found한 다음 을 인쇄합니다 .xyzif생성되었지만 완료될 때까지 사용할 수 없습니다.

관련 정보