Mac BigSur의 Bash 스크립트 구문 오류: 잘못된 산술 연산자

Mac BigSur의 Bash 스크립트 구문 오류: 잘못된 산술 연산자

여기서 이상한 오류가 발생합니다. 다음과 같은 json 구조가 있습니다.

BACKUP_REPOS='''
[
    {"name":"my.server1", "hash":"server1-hash"},
    {"name":"my.server2", "hash":"server2-hash"},
    {"name":"my.server3", "hash":"server3-hash"}
]
'''

내가 하려는 것은 jq다음 기능을 사용하여 선택 가능한 메뉴를 생성하는 것입니다.

# generate the server menu
server_menu( ) {

    # hold some arrays
    declare -a _name _hash;

    while read -r _server _pw; do

        # hold the selected item
        _name[$_server]=$_server;
        _hash[$_server]=$_pw;

    # end the loop generation
    done < <( jq -rc '.[] | "\(.name) \(.hash)"' <<< "$BACKUP_REPOS" )

    # now loop the resultset
    select _server in "${!_name[@]}"; do 
        [ -n "$_server" ] && break;
    done;

    # return the server and hash
    SELECTED_SERVER=${_name[$_server]};
    SELECTED_HASH=${_hash[$_server]};

}

이제 Ubuntu 18+에서는 제대로 작동하지만 Mac BigSur 터미널에서는 오류가 발생합니다. 오류는 다음과 같습니다. syntax error: invalid arithmetic operator (error token is ".server1") on line 82전체 코드 파일에는 다음 줄이 있습니다._name[$_server]=$_server;

여기서 내가 어디서 잘못됐나요? 이 시점에서 유일한 관심사는 내 Mac에서 이 스크립트를 실행하는 것입니다. 여러 복사본을 보관할 수 있습니다.

티아

답변1

macOS와 함께 제공되는 기본 bash 버전에서는 불가능한 연관 배열을 사용하려는 것 같습니다. 따라서 이를 수행하려면 bash를 버전 4 이상으로 업데이트해야 하지만 다음 사항도 변경해야 합니다.

declare -a _name _hash

도착하다

declare -A _name _hash

표준 배열로서 인덱스에 포함될 수 있는 유일한 항목은 정수이며, 산술 확장을 수행할 수 있으므로 [ ... ]확장하는 정수가 아닌/잘못된 연산으로 인해 질식하게 됩니다.

답변2

~처럼jesse_b가 지적했어요, 문제는 배열이 연관 배열이 아니라는 것입니다. macOS에서 연관 배열을 처리하는 방법을 모르므 bashzsh일반 배열을 다시 작성하거나 사용하는 것이 좋습니다. 또는 bashHomebrew를 사용하여 업데이트된 셸을 설치 declare -a하고 declare -A.

다음은 bashmacOS의 기본 설정에 적용됩니다( jq이 설정도 설치되어 있다고 가정).

menu_select_server () {
        local server_json=file.json  # JSON containing server config

        # Set positional parameters to list of servers
        eval "$( jq -r '[ "set --", (.[].name|@sh) ] | @tsv' "$server_json" )"

        # Select wanted server
        local PS3='Select server: '
        select SELECTED_SERVER; do
                [[ -n $SELECTED_SERVER ]] && break
        done

        # Get corresponding hash
        SELECTED_HASH=$(
                jq -r --argjson i "$REPLY" \
                        '.[($i-1)].hash' "$server_json"
        )
}

여기서는 파일을 두 번 구문 분석합니다. 한 번은 서버 목록을 가져오고 한 번은 선택한 서버에 대한 해시를 가져옵니다. 하지만 수행 중인 작업과 비슷한 작업을 수행하는 것은 쉽습니다. 다음을 사용하여 해시를 가져오는 것으로 전환하면 $REPLY됩니다 select. 고리:

menu_select_server () {
        local server_json=file.json  # JSON containing server config

        local name hash
        local hashes=()
        set --

        # Read names into list of positional parameters
        # Read hashes into "hashes" array
        while IFS=$'\t' read -r name hash; do
                set -- "$@" "$name"
                hashes+=( "$hash" )
        done < <( jq -r '.[] | [ .name, .hash ] | @tsv' "$server_json" )
        # or:
        #     jq -r 'map([ .name, .hash ] | @tsv)[]' "$server_json"

        # Select wanted server
        local PS3='Select server: '
        select SELECTED_SERVER; do
                [[ -n $SELECTED_SERVER ]] && break
        done

        # Get corresponding hash
        SELECTED_HASH=${hashes[REPLY-1]}
}

관련 정보