여기서 이상한 오류가 발생합니다. 다음과 같은 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에서 연관 배열을 처리하는 방법을 모르므 bash
로 zsh
일반 배열을 다시 작성하거나 사용하는 것이 좋습니다. 또는 bash
Homebrew를 사용하여 업데이트된 셸을 설치 declare -a
하고 declare -A
.
다음은 bash
macOS의 기본 설정에 적용됩니다( 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]}
}