왜 사람은 .profile에 정의된 기능에 대해 불평합니까?

왜 사람은 .profile에 정의된 기능에 대해 불평합니까?

저는 배쉬 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

.bashrcBash가 시작될 때 오류나 경고가 표시되지 않기 때문에 그 자체에는 아무런 문제가 없다고 확신합니다 . 추가 디버깅을 통해 .profile구매한 것으로 나타났습니다..bashrc

# source Bash customizations
[ -n "${BASH_VERSION}" ] && [ -r "${HOME}/.bashrc" ] && . "${HOME}/.bashrc"

이렇게 ~/.bashrc시작했어요

# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return

질문:

  1. 왜 시작하기 전에 자원을 확보 man해야 합니까 ?.profile
  2. 이중 확인에도 불구하고 위 코드가 Bash가 아닌 셸에서 구문 분석되는 이유는 무엇입니까?
    1. Bash가 아닐 때 .profile소스 코드를 얻지 못하는지 확인하십시오..bashrc
    2. .bashrc추가 처리를 중지하려면 비대화식으로 체크인하세요.

@muru의 의견을 통해 Bash가 아닌 쉘에서 가져올 위험이 있으므로 내보낸 함수에 Bashism을 포함해서는 안 된다는 것을 깨달았습니다. 남은 질문 하나:man전화하나요 sh?.

답변1

man당신의 것을 읽지는 않지만 일부 명령줄을 해석하기 위해 ~/.profile실행될 것입니다 (또는 적어도 내 시스템에서는 스크립트 래퍼를 해석합니다 ). 그리고 당신의 시스템에서는 다음과 같습니다 .shnroffshgroffshbash수입bashexport -f(shellshock 이후 명명된 변수에서 BASH_FUNC_funcname%%)에 의해 내보낸 함수, sh.

extglob여기서는 이 옵션 에 따라 구문이 달라지는 함수를 내보내고 있습니다 . 따라서 실행 sh( 모드 bash에서 )하고 내보낸 모든 기능을 가져올 때 기본적으로 활성화된 옵션( 모드에서 여부)이 아니기 sh때문에 문제를 해결할 수 없습니다 .extglobsh

IOW, 함수 내보내기는 해당 함수가 모든 호출에서도 사용된다는 것을 의미합니다 bash. sh따라서 sh이러한 함수의 구문이 및 -as-in-default 설정과 호환되는지 bash주의해야 합니다. 그렇지 않으면 함수 내보내기를 모두 피해야 합니다. 이러한 함수가 호출되지 않더라도 이러한 함수의 코드도 구문 분석됩니다.bashshbash

바라보다:

$ 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또는 옵션( 최근 버전에서 설정된 옵션 제외)과 반대) 함수가 호출될 때까지 지연 구문 분석을 사용 하고 옵션이 설정되었습니다.kshsetevalextglob

여기서도 다음을 수행할 수 있습니다.

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에서는 드물지만 다른 구현)일 수 있습니다.nroffnroffsh

대화형 사용의 경우 bash는 을 로드하므로 .bashrc환경에 함수를 두는 것은 의미가 없습니다. 해당 정의를 .bashrc, 또는 from 에 넣으십시오 .bashrc. 자신의 스크립트의 경우 함수 정의를 원하는 파일에 넣으십시오( .profile또는 .bashrc자체가 포함되어 있기 때문입니다). 모든 스크립트에 대해 실행해서는 안 되는 것) 및 스크립트에 또는 명령을 넣으십시오 source. .함수 정의를 내보내는 데는 이점이 거의 없습니다. 이를 사용하는 스크립트를 제어하기 때문에 정의된 위치를 가져오도록 할 수 있습니다. Bash가 기본 설정에서 함수를 구문 분석할 수 없으면 함수가 작동할 방법이 없습니다.

관련 정보