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
한 다음 을 인쇄합니다 .xyz
예if
생성되었지만 완료될 때까지 사용할 수 없습니다.