首页 > 解决方案 > 如何将正确的键和值从 jq 拉到 bash shell 脚本中的数组中

问题描述

我有一个格式如下的 json 文件:

{
  "ServerName1": {
    "localip": "192.168.1.1",
    "hostname": "server1"
  },
  "ServerName2": {
    "localip": "192.168.1.2",
    "hostname": "server2"
  },
  "ServerName3": {
    "localip": "192.168.1.3",
    "hostname": "server3"
  }
}

我正在尝试编写一个使用 Dialog 创建菜单来运行 ssh 连接命令的 shell 脚本。我正在使用 jq 进行解析,但无法通过第一个对象级别。我们有很多服务器,这将使连接它们变得更加容易。我的 Dialog 语句可以很好地处理静态数据,但我们正在尝试使用包含其余数据的 json 文件填充它。所以我正在自杀,试图弄清楚如何将 localip 和主机名放入一个数组中以循环进入 Dialog 命令或可以有效地做同样事情的东西,而我到目前为止所做的只是吐出

Servername1 = {"localip":"192.168.1.1","hostname":"server1"}

在每一行。我是一个 shell 脚本新手,但这现在很混乱。

这是迄今为止我一直在使用的 jq 命令:

jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" config.json

这是适用于静态数据的 Dialog 命令:

callssh(){
  clear
  ssh $1@$2
}

## Display Menu ##
dialog --clear --title "SSH Relayer"\
    --menu "Please choose which server \n\
    with which you would like to connect" 15 50 4 \ 
    "Server 1" "192.168.1.1"\
    "Server 2" "192.168.1.2"\
    "Server 3" "192.168.1.3"\
    Exit "Exit to shell" 2>"${INPUT}"

menuitem=$(<"${INPUT}")

case $menuitem in
    "Server 1") callssh $sshuser 192.168.1.1;;
    "Server 2") callssh $sshuser 192.168.1.2;;
    "Server 3") callssh $sshuser 192.168.1.3;;
    Exit) clear 
          echo "Bye!";;
esac

感谢您提供任何帮助或指出正确的方向。

标签: jsonbashshelldialogjq

解决方案


要基于 config.json 创建一个将主机名映射到 IP 地址的 bash 数组:

declare -A ip_of

# Emit lines of the form:
# hostname localip (without quotation marks)
function hostname_ip {
 local json="$1"
 jq -r '.[] | "\(.hostname) \(.localip)"' "$json"
}

while read -r hostname ip ; do
    ip_of["$hostname"]="$ip"
done < <(hostname_ip config.json)

你可以像这样循环遍历这个 bash 数组:

for hostname in "${!ip_of[@]}" ; do
  echo hostname=$hostname "=>" ${ip_of[$hostname]}
done

例如,假设“对话框”显示主机名,您可以将case语句替换为:

callssh "$sshuser" "${ip_of[$menuitem]}"

推荐阅读