zsh에서 실행할 때 Bash 스크립트가 "잘못된 아래 첨자 범위에 할당됨"을 발생시킵니다.

zsh에서 실행할 때 Bash 스크립트가 "잘못된 아래 첨자 범위에 할당됨"을 발생시킵니다.

고쳐 쓰다 이것 좀 봐봐협회, 0 대신 1로 시작하도록 배열 첨자를 업데이트했는데 배열 변수가 올바르게 읽혀진 것 같습니다.

#!/bin/bash

#Root folders for Git update.
    ROOT[1]="/Users/ayusman/dev/repos1"
    ROOT[2]="/Users/ayusman/dev/repos2"

#do some things with the ROOT variable.

그런데 앞서 선언한 쉘 함수가 인식되지 않아서 다른 곳에서 오류가 보이기 시작했습니다.

명령을 찾을 수 없습니다: git

그래서 일반적인 질문은 다음과 같습니다.

bash 쉘에서 완벽하게 작동하는 쉘 스크립트를 zsh 쉘로 이식하려면 어떻게 해야 합니까?

최근에 Mac을 macOS Catalina 10.15.2로 업그레이드했습니다.

내 쉘 스크립트 중 하나는 다음과 같습니다.

#!/bin/bash

#Root folders for Git update.
    ROOT[0]="/Users/ayusman/dev/repos1"
    ROOT[1]="/Users/ayusman/dev/repos2"

#do some things with the ROOT variable.

내 기본 쉘이 bash 쉘이었을 때 이것은 잘 작동했습니다. 여기서 내가 한 일은 쉘 스크립트에서 사용할 배열 변수에 일부 폴더를 추가하는 것입니다. 업그레이드를 릴리스하고 기본 셸을 zsh로 설정한 후 스크립트를 시작할 때(.zsrc 파일의 별칭을 통해) 다음 오류가 발생합니다.

[ayusman@~10:39AM]$updateExpediaGitRepos 
/Users/ayusman/scripts/updateGitRepos.sh:250: ROOT: assignment to invalid subscript range
[ayusman@~10:39AM]$

쉘을 다시 bash로 변경할 때(아래 표시된 대로 chsh를 실행하여) 동일한 스크립트가 예상대로 실행되는지 확인했습니다.

chsh -s /bin/bash

따라서 본질적으로 질문은 기존 bash 스크립트를 사용하지 않고 zsh 쉘에서 실행할 수 있습니까?

고마워요, 아유슈만

답변1

zsh스크립트에 대한 설명을 요청하는 것 같습니다 . 당신은 updateExpediaGitRepos그것이 무엇인지 말하지 않았지만 나는 생각했습니다.alias 원천이 스크립트는 .또는 source내장 명령을 사용합니다. 이 명령은 현재 쉘 해석기에 파일의 코드를 해석하도록 지시하므로 shebang( #! /bin/bash)은 관련이 없습니다. Shebang은 시도하는 경우에만 커널에서 사용됩니다.구현하다스크립트.

아마도 이는 updateGitRepos.sh사용자 쉘의 속성(예: 환경 변수 설정, 함수 정의, 별칭 정의 등)을 수정하여 사용자 환경을 사용자 정의하는 데 사용되며, 이 경우 실행하는 데 도움이 되지 않습니다.

bash두 가지 서로 다르고 호환되지 않는 언어에 대한 통역사 입니다 zsh(둘 다 Bourne 쉘, Korn 쉘 및 C 쉘에서 많은 영감을 얻기 때문에 공통점이 있지만). 일반적으로 한 사람이 다른 사람을 위해 작성된 코드를 해석할 수 있을 것이라고 기대할 수는 없습니다.

특히 배열은 매우 다르게 구현됩니다.

zsh배열은 실제로 셸에서 일반적으로 사용되는 대부분의 다른 셸 및 도구와 마찬가지로 인덱스가 1에서 시작하는 배열입니다(자세한 내용은 다음을 참조하세요).Zsh 배열의 첫 번째 요소에 인덱스가 0이 아닌 1인 이유가 있나요?).

bash배열은 Korn 쉘에서 복사됩니다. 이는 희소 배열(양의 정수로 제한된 키를 갖는 연관 배열과 유사)이며 인덱스는 0에서 시작합니다.

zsh여러 지원시뮬레이션다른 쉘용으로 작성된 코드를 해석하는 데 사용할 수 있습니다. 특히 bash배열을 사용하여 스크립트를 구문 분석하는 데 유용한 ksh 에뮬레이션 모드가 있습니다.

emulate ksh

시작하세요.

또는:

emulate ksh -c 'some code'

이 시뮬레이션 모드에서 코드를 평가합니다. 이 모드에서 선언된 함수는 시뮬레이션 모드를 상속합니다.

또한 ksh시뮬레이션 모드에서는 이 KSH_ARRAYS옵션이 켜져 있어 배열 인덱스가 0부터 시작됩니다(그러나 여전히 희박하지는 않음).

따라서 여기에서 별칭을 수정하여 다음과 같이 시도해 볼 수 있습니다.

emulate ksh -c '. /Users/ayusman/scripts/updateGitRepos.sh'

바꾸다

. /Users/ayusman/scripts/updateGitRepos.sh

귀하의 경우에는 이것으로 충분할 수도 있고 충분하지 않을 수도 있습니다. 이 시뮬레이션 모드만개선하다호환성을 위해 kshzsh를 ksh 복제본으로 만들지 않습니다. 그리고 ksh는 bash가 아닙니다.

사용자의 셸을 소스로 사용 하려면 updateGitRepos.sh지원되는 각 셸에 대해 각각 적절한 언어로 작성된 다른 버전의 스크립트를 제공하거나 지원되는 모든 셸과 호환되는 구문을 사용해야 합니다. 일반적으로 배열은 제외됩니다. (그러나 참조어레이에 대한 테스트 셸 지원가능한 방법).

스크립트가 사용자의 대화형 셸에 의해 해석되지 않고 단순히 실행되는 경우 /path/to/the/scriptshebang 덕분에 스크립트를 실행하면 올바른 해석기가 시작되어 해석할 수 있습니다. not source /path/to/the/script, not zsh /path/to/the/script( bash /path/to/the/script여기에서도 다음과 같이 작동합니다. 이는 bash스크립트입니다(오해의 소지가 있는 .sh확장에도 불구하고)).

답변2

이 동작은 zsh셸에서 배열이 작동하는 방식으로 인해 발생하며 해당 배열의 인덱싱은 1아니요존재하다 0. 따라서 인덱스의 요소에 액세스하면 0현재 보고 있는 오류가 발생합니다.

zsh매뉴얼 에서 -15.2.1 배열 첨자

15.2.1 Array Subscripts

아래 첨자를 사용하여 배열의 개별 요소를 선택할 수 있습니다. 양식의 첨자는 [exp]단일 요소를 선택합니다 exp. 여기서 exp는 마치 둘러싸인 것처럼 산술적으로 확장됩니다 $((...)). 요소 번호는 다음으로 시작합니다.1, KSH_ARRAYS이 옵션이 설정되지 않은 경우 0부터 번호가 매겨집니다.

이 옵션이 설정되지 않은 경우 KSH_ARRAYS기본값은 아래 첨자를 사용하여 배열 요소에 액세스하는 것입니다.0으로 평가하고 빈 문자열을 반환합니다., 하지만이러한 요소에 쓰려는 시도는 오류로 처리됩니다.. 이전 버전과의 호환성을 위해 KSH_ZERO_SUBSCRIPT아래 첨자 값 0과 1이 동일하도록 이 옵션을 설정할 수 있습니다. 옵션 설명의 옵션 설명을 참조하세요.

따라서 index 로 시작하는 배열의 동작을 시뮬레이션하려면 0스크립트 상단에서 이 옵션을 설정하세요.

setopt ksh_arrays

zshshe-bang 인터프리터가 로 설정되어 있어도 스크립트가 동작을 나타내는 이유를 명확히 하기 위해 #!/bin/bash스크립트는 명시적 호출로 실행될 수 있으며, zsh <script>이 경우 운영 체제는 스크립트 상단의 인터프리터 줄을 인식하지 못합니다. 스크립트 자체가 실행 가능( chmod +x)되고 를 사용하여 실행되면 ./<script>스크립트 상단에 제공된 인터프리터가 적용됩니다.

관련 정보