문자열 교체의 경우 bash shebang은 작동하지만 sh shebang은 작동하지 않는 이유는 무엇입니까?

문자열 교체의 경우 bash shebang은 작동하지만 sh shebang은 작동하지 않는 이유는 무엇입니까?

나는 buildkite 스크립트에서 발생한 문제를 추적해 왔으며 이것이 내가 얻은 결과입니다.

먼저 docker 이미지의 셸을 입력합니다.

docker run --rm -it --entrypoint bash node:12.21.0

이 Docker 이미지에는 텍스트 편집기가 없으므로 파일에 연결하여 셸 스크립트를 만들었습니다.

touch a.sh
chmod +x a.sh
printf '#!/bin/sh\necho ${1:0:1}' >> a.sh

touch b.sh
chmod +x b.sh
printf '#!/bin/bash\necho ${1:0:1}' >> b.sh

이제 스크립트를 실행합니다.

./a.sh hello
>./a.sh: 2: ./a.sh: Bad substitution 
./b.sh hello 
>h

누군가 여기에 문제가 무엇인지 간단히 말해 줄 수 있습니까?

이 AskUbuntu 질문bash와 sh는 다른 쉘이며 많은 시스템에서 sh는 bash에 심볼릭 링크됩니다.

이 도커 이미지에 정확히 무슨 일이 일어났나요? 내가 어떻게 알 수 있나요?

답변1

/bin/shPOSIX 쉘일 것으로 예상되며 POSIX 쉘일 것입니다.매개변수 확장의 하위 문자열을 인식하지 못함.

POSIX"명령 해석기(또는 "셸")를 포함한 표준 운영 체제 인터페이스 및 환경을 정의합니다." 전통적인 Unix 스타일 환경에서 널리 사용되는 표준입니다. 바라보다POSIX란 정확히 무엇입니까?더 넓은 설명을 위해. POSIX 기반 환경에서는 /bin/shPOSIX 스타일 쉘이 제공되어야 하며, /bin/shShebang으로 사용되는 스크립트에서는 POSIX 기능에만 의존할 수 있습니다(대부분의 실제 구현에서는 /bin/sh더 많은 기능을 제공하지만). 고급 쉘을 사용하는 것은 완벽하지만 이에 따라 shebang을 조정해야 합니다.

귀하의 스크립트는 bash 기능에 의존하기 때문에 올바른 shebang은 그것이 실행되는 환경이 무엇 #!/bin/bash이든 상관없습니다 . #!/usr/bin/env bash어떤 경우에는 그냥 작동할 수도 있지만 #!/bin/sh그것은 단지 행복한 우연일 뿐입니다.

답변2

스크립트는 매개변수 확장에 POSIX가 아닌 확장을 사용하므로 대부분의 쉘에서는 실행되지 않습니다.

bash이는 스크립트가 다음과 같은 쉘에 의해 실행되도록 강제하여 수행할 수 있습니다.POSIX 쉘 스크립트 작성, 이는 많은 상황에서 좋은 습관입니다.

zsh불행하게도 인수의 첫 번째 문자를 가져오는 with 와 같은 우아한 방법 은 없습니다 $1[1]. 따라서 using을 사용할 수 있습니다.

  • "$(echo "$1" | cut -c1-1)"또는
  • "$(printf %.1s "$1")"또는
  • 이상한 점은 문자열에서 "${1%"${1#?}"}"첫 번째 문자( )가 없는 문자열을 제거한다는 것입니다.${1#?}

관련 정보