저는 배쉬 5.1.8을 사용하고 있습니다. 실행하면 man
매뉴얼 페이지가 표시되지만 다음 오류가 발생합니다.
man ps
sh: bat: line 10: syntax error near unexpected token `('
sh: bat: line 10: ` *.?(ba)sh)'
sh: error importing function definition for `bat'
내 생각에 일부 쉘( sh
)은 Bashism을 짜증나게 하는 것 같습니다. Bash-isms를 다음에서 제거하면 ~/.bashrc
:
function bat {
# lines snipped for brevity
case "$f" in
*.rs ) opt_syntax="--syntax=rust";;
*.?(ba)sh ) opt_syntax="--syntax=shellscript";;
*.?(m)m ) opt_syntax="--syntax=objc";;
esac
# lines snipped for brevity
}
export -f bat
.bashrc
Bash가 시작될 때 오류나 경고가 표시되지 않기 때문에 그 자체에는 아무런 문제가 없다고 확신합니다 . 추가 디버깅을 통해 .profile
구매한 것으로 나타났습니다..bashrc
# source Bash customizations
[ -n "${BASH_VERSION}" ] && [ -r "${HOME}/.bashrc" ] && . "${HOME}/.bashrc"
이렇게 ~/.bashrc
시작했어요
# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return
질문:
- 왜 시작하기 전에 자원을 확보
man
해야 합니까 ?.profile
- 이중 확인에도 불구하고 위 코드가 Bash가 아닌 셸에서 구문 분석되는 이유는 무엇입니까?
- Bash가 아닐 때
.profile
소스 코드를 얻지 못하는지 확인하십시오..bashrc
.bashrc
추가 처리를 중지하려면 비대화식으로 체크인하세요.
- Bash가 아닐 때
@muru의 의견을 통해 Bash가 아닌 쉘에서 가져올 위험이 있으므로 내보낸 함수에 Bashism을 포함해서는 안 된다는 것을 깨달았습니다. 남은 질문 하나:왜 man
전화하나요 sh
?.
답변1
man
당신의 것을 읽지는 않지만 일부 명령줄을 해석하기 위해 ~/.profile
실행될 것입니다 (또는 적어도 내 시스템에서는 스크립트 래퍼를 해석합니다 ). 그리고 당신의 시스템에서는 다음과 같습니다 .sh
nroff
sh
groff
sh
bash
수입bash
의 export -f
(shellshock 이후 명명된 변수에서 BASH_FUNC_funcname%%
)에 의해 내보낸 함수, sh
.
extglob
여기서는 이 옵션 에 따라 구문이 달라지는 함수를 내보내고 있습니다 . 따라서 실행 sh
( 모드 bash
에서 )하고 내보낸 모든 기능을 가져올 때 기본적으로 활성화된 옵션( 모드에서 여부)이 아니기 sh
때문에 문제를 해결할 수 없습니다 .extglob
sh
IOW, 함수 내보내기는 해당 함수가 모든 호출에서도 사용된다는 것을 의미합니다 bash
. sh
따라서 sh
이러한 함수의 구문이 및 -as-in-default 설정과 호환되는지 bash
주의해야 합니다. 그렇지 않으면 함수 내보내기를 모두 피해야 합니다. 이러한 함수가 호출되지 않더라도 이러한 함수의 코드도 구문 분석됩니다.bash
sh
bash
바라보다:
$ env 'BASH_FUNC_f%%=() { case x in ?(x)) echo x; esac; }' bash -O extglob -c f
x
$ env 'BASH_FUNC_f%%=() { case x in ?(x)) echo x; esac; }' bash -c f
bash: f: line 0: syntax error near unexpected token `('
bash: f: line 0: `f () { case x in ?(x)) echo x; esac; }'
bash: error importing function definition for `f'
bash: line 1: f: command not found
함수에 이와 같이 구문 분석에 영향을 미치는 기본이 아닌 옵션이 필요한 경우 extglob
다음과 같이 정의할 수 있습니다.
f() (
shopt -s extglob
eval '
function body here
'
)
export -f f
이는 옵션이 함수 실행 중에만 설정되도록 서브셸에서 코드를 실행하고( 로컬 범위가 없는 bash
옵션 zsh
또는 옵션( 최근 버전에서 설정된 옵션 제외)과 반대) 함수가 호출될 때까지 지연 구문 분석을 사용 하고 옵션이 설정되었습니다.ksh
set
eval
extglob
여기서도 다음을 수행할 수 있습니다.
f() (
shopt -s extglob
pattern='*.?(ba)sh'
case ... in
($pattern)...
esac
)
그러나 다음과 같이 할 수도 있습니다.
f() {
case ... in
(*.sh | *.bash) ...
esac
}
이것은 sh
필요하지 않습니다 extglob
.
답변2
함수, 특히 기본이 아닌 bash 구성이 필요한 함수를 내보내지 마십시오.
내보낸 함수는 bash 기능이므로 다른 셸에 영향을 주지 않습니다. 그러나 이는 bash에 대한 모든 호출에 영향을 미칩니다. 함수에서 extglob
이 옵션을 활성화해야 합니다. 그렇지 않으면 함수 실행이 실패할 뿐만 아니라분석하다함수 정의에 실패했습니다. 함수를 내보낼 때 bash는 작업을 시작하기 전에 함수 정의를 구문 분석합니다.
쉘은 sh
유닉스 시스템의 글루 코드입니다. 대화형으로 사용할 뿐만 아니라 뒤에서도 광범위하게 사용됩니다. 프로시저 호출은 sh
다양한 목적으로 사용됩니다. man
여러 개의 동반 프로그램을 호출합니다. 그 중 하나는 셸을 호출할 수 있습니다. 예를 들어, Linux에서 의 nroff
일반적인 구현(맨 페이지의 소스 코드를 터미널의 서식 있는 텍스트로 변환하는 기본 명령)은 groff
전통적인 . , 배포판에 따라 dash, bash(또는 Linux에서는 드물지만 다른 구현)일 수 있습니다.nroff
nroff
sh
대화형 사용의 경우 bash는 을 로드하므로 .bashrc
환경에 함수를 두는 것은 의미가 없습니다. 해당 정의를 .bashrc
, 또는 from 에 넣으십시오 .bashrc
. 자신의 스크립트의 경우 함수 정의를 원하는 파일에 넣으십시오( .profile
또는 .bashrc
자체가 포함되어 있기 때문입니다). 모든 스크립트에 대해 실행해서는 안 되는 것) 및 스크립트에 또는 명령을 넣으십시오 source
. .
함수 정의를 내보내는 데는 이점이 거의 없습니다. 이를 사용하는 스크립트를 제어하기 때문에 정의된 위치를 가져오도록 할 수 있습니다. Bash가 기본 설정에서 함수를 구문 분석할 수 없으면 함수가 작동할 방법이 없습니다.