
ここで奇妙なエラーが発生します。次の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"
)
}
ここでは、ファイルを2回解析します。一度はサーバーのリストを取得し、一度は選択したサーバーのハッシュを取得します。ただし、実行している作業と同様の作業を実行するのは簡単です。以下を使用してハッシュをインポートに切り替え$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]}
}