【问题标题】:Use variable in jq read query在jq读取查询中使用变量
【发布时间】:2019-12-01 15:32:02
【问题描述】:

我有以下 json 文件

cat permissions.json

{
  "foo1.bar1@email.com": [
    "projects/development/roles/superadmin",
    "compute.networkAdmin"
  ],
  "foo2.bar2@email.co": [
    "compute.networkAdmin"
  ]
}

现在我可以用jq 很好地完成这样的事情

$ jq -r '.["foo1.bar1@email.com"]' permissions.json
[
  "projects/development/roles/superadmin",
   "compute.networkAdmin"
]

现在邮件需要来自一个变量

所以我的 for 循环是这样的

for USER in $(jq -r 'keys[]' permissions.json)
do
  echo ${USER}
  for ROLE in $(jq -r '.["$USER"][]' permissions.json)
  do
    echo "User ${USER} has role ${ROLE}"
  done
done

但是当我运行时

./compare-permissions.sh
foo1.bar1@email.com
jq: error (at permissions.json:9): Cannot iterate over null (null)
foo2.bar2@email.co
jq: error (at permissions.json:9): Cannot iterate over null (null)

我尝试将 var 作为--arg 发送。我做过类似的事情

USER=foo1.bar1@email.com
jq -r --arg USER "$USER" '.["$USER"][] | select(.[]==$USER)'  permissions.json

但是结果是空的。那么如何使用电子邮件作为变量并使用jq 从中提取权限?

【问题讨论】:

  • 请注意,for var in $(anything) 是不好的做法——如果在 jq 的输出中有一个被空格包围的 *,您会发现自己在遍历文件名(这只是许多可能的错误之一)。请参阅 BashPitfalls #1 以获取解释,BashFAQ #1 了解逐行迭代输入流的最佳实践方法的解释。
  • 如果你真的想保留当前的结构,在你的代码前面加上 IFS=$'\n' 并不能修复不需要的通配符(set -f 会这样做,但它会禁用 all globbing,所以你以后经常想用set +f 来反转它),但单独更改 IFS确实 至少可以阻止 jq 的输出除了换行符之外的其他空格。

标签: json bash variables iteration jq


【解决方案1】:

不要使用字符串插值;将变量作为参数传递。

for user in $(jq -r 'keys[]' permissions.json)
do
  echo ${user}
  for role in $(jq --arg u "$user" -r '.[$u][]' permissions.json)
  do
    echo "User ${user} has role ${role}"
  done
done

另外,不要使用 for 循环来迭代命令的输出。使用while 循环和read 命令。

while IFS= read -r user; do
  echo "$user"
  while IFS= read -r role; do
    echo "User $user has role $role"
  done < <(jq --arg u "$user" -r '.[$u][]' permissions.json
done < <(jq -r 'keys[]' permissions.json)  

但是,您可能根本不需要 shell 循环。

% jq -r 'keys[] as $user | .[$user][] | "User \($user) has role \(.)"' permissions.json
User foo1.bar1@email.com has role projects/development/roles/superadmin
User foo1.bar1@email.com has role compute.networkAdmin
User foo2.bar2@email.co has role compute.networkAdmin

【讨论】:

  • 为无壳循环的答案竖起大拇指,grumble 为保持for var in $(...) 成语。
  • 呃,fiiiine。 :)
【解决方案2】:

$USER 不会被扩展,因为它是在单引号中。您可以使用 arg:

#!/bin/bash                                                                                                                                                                                                        

for USER in $(jq -r 'keys[]' permissions.json)                                                                                                                                                                     
do                                                                                                                                                                                                                 
  echo ${USER}                                                                                                                                                                                                     
  for ROLE in $(jq --arg u "$USER" -r '.[$u][]' permissions.json)                                                                                                                                                  
  do                                                                                                                                                                                                               
    echo "User ${USER} has role ${ROLE}"                                                                                                                                                                           
  done                                                                                                                                                                                                             
done  

或为一个用户提取权限:

USER=foo1.bar1@email.com                                                                                                                                                                                           
jq --arg USER "$USER" -r '.[$USER][]' permissions.json

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2021-04-01
    • 2018-01-16
    • 2016-05-05
    • 1970-01-01
    • 2014-03-21
    • 2021-11-16
    相关资源
    最近更新 更多