【问题标题】:How to print path and key values of JSON file using JQ如何使用 JQ 打印 JSON 文件的路径和键值
【发布时间】:2020-01-12 01:53:09
【问题描述】:

我想逐行打印包含键值的 文件的每个路径和值。我希望输出用逗号分隔,或者至少很容易使用 Linux 命令行工具进行剪切和排序。鉴于以下,我得到了 代码,它似乎对测试JSON 执行此操作,但我不确定它是否适用于所有情况或者是否是正确的方法。

中是否有自动执行此操作的函数?如果没有,是否有“最简洁的最佳方式”?

我的愿望是这样的:

$ cat short.json | jq -doit '.'
Reservations,0,Instances,0,ImageId,ami-a
Reservations,0,Instances,0,InstanceId,i-a
Reservations,0,Instances,0,InstanceType,t2.micro
Reservations,0,Instances,0,KeyName,ubuntu


测试 JSON:

$ cat short.json | jq '.'
{
  "Reservations": [
    {
      "Groups": [],
      "Instances": [
        {
          "ImageId": "ami-a",
          "InstanceId": "i-a",
          "InstanceType": "t2.micro",
          "KeyName": "ubuntu"
        }
      ]
    }
  ]
}  

推荐代码:
https://unix.stackexchange.com/questions/561460/how-to-print-path-and-key-values-of-json-file
支持:
https://unix.stackexchange.com/questions/515573/convert-json-file-to-a-key-path-with-the-resulting-value-at-the-end-of-each-k
JQ代码太长太复杂了!

jq -r '
paths(scalars) as $p
  | [ ( [ $p[] | tostring ] | join(".") )
    , ( getpath($p) | tojson )
    ]
  | join(": ")
' short.json  

Result:  
Reservations.0.Instances.0.ImageId: "ami-a"
Reservations.0.Instances.0.InstanceId: "i-a"
Reservations.0.Instances.0.InstanceType: "t2.micro"
Reservations.0.Instances.0.KeyName: "ubuntu"  


【问题讨论】:

    标签: json json jq jq jq json path jq


    【解决方案1】:

    实现请求格式的简单jq查询:

     paths(scalars) as $p
     | $p + [getpath($p)] 
     | join(",")
    

    如果您的 jq 是古老的并且无法升级,请在上面的最后一行之前插入 | map(tostring)

    使用 -r 选项输出

    Reservations,0,Instances,0,ImageId,ami-a
    Reservations,0,Instances,0,InstanceId,i-a
    Reservations,0,Instances,0,InstanceType,t2.micro
    Reservations,0,Instances,0,KeyName,ubuntu
    

    警告

    如果键或原子值包含“,”,那么当然不建议使用逗号。因此,最好使用不能出现在 JSON 键或原子值中的字符,例如 TAB。因此考虑使用@tsv

    paths(scalars) as $p
    | $p + [getpath($p)]
    | @tsv
    

    (上面关于 jq 古代版本的评论也适用于此。)

    【讨论】:

    • 请原谅格式,但我对这些答案有一些问题。 $ 猫短.json | jq -r '路径(标量)作为 $p | $p + [getpath($p)] | join(",")' jq: error (at :15): string (",") and number (0) cannot be added and the first line of the tsv output does not tab delimit the value but do for后续行。 $ 猫短.json | jq -r '路径(标量)作为 $p| $p + [getpath($p)]| @tsv' 预订 0 实例 0 ImageId ami-a
    • AWS ec2 和 GCE Debian 实例使用 jq-1.5-1-a5b5cbe。 2018年好像有更新的1.6版本,我试试看。
    • 使用 1.6 版... tsv 输出的第一行在 path 和 value 之间不包含制表符分隔符,但在后续行中包含制表符分隔符。
    • 对于第一个示例,map(tostring) 选项和升级到版本 1.6 选项都按描述工作。谢谢!
    • tsv 示例无法使用制表符分隔第一行的值。有什么可以调整的吗?
    【解决方案2】:

    将其作为流读取。

    $ jq --stream -r 'select(.[1]|scalars!=null) | "\(.[0]|join(".")): \(.[1]|tojson)"' short.json
    

    【讨论】:

    • 杰夫,很抱歉格式化,但我收到以下错误:$ jq --stream -r 'select(.[1]|scalars) | "(.[0]|join(".")): (.[1]|tojson)"' short.json jq: error (at short.json:7): string (".") and number (0 ) 无法添加 jq: 错误 (at short.json:8): 字符串 (".") 和数字 (0) 无法添加 jq: 错误 (at short.json:9): 字符串 (".") 和数字(0) 无法添加 jq: error (at short.json:11): string (".") 和数字 (0) 无法添加
    • 听起来您使用的是旧版本的 jq,您需要将键的所有部分转换为字符串。 select(.[1]|scalars) | "\([.[0][]|tostring]|join(".")): \(.[1]|tojson)"
    • 这两个例子都有效,谢谢!虽然没有我希望的那么紧凑。我真的很希望这种类型的输出能够作为 JQ 的一个开关。
    • 嗯,它大部分都在流中,只是不是你想要的格式。
    • @JeffMercado - 如果您提出的解决方案是通用的,select 应该是 select(length==2)
    猜你喜欢
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    相关资源
    最近更新 更多