【问题标题】:Grouping and sorting JSON records in Bash在 Bash 中对 JSON 记录进行分组和排序
【发布时间】:2021-08-08 23:02:24
【问题描述】:

我正在使用 curl 获取 JSON 文件。我的问题是我想在一行中获得 4 个单词的组,然后换行,并按第一列排序。

我正在尝试:

curl -L 'http://mylink/ | jq '.[]| .location, .host_name, .serial_number, .model'

我来了

"Office-1"    
"work-1"    
"11xxx111"    
"hp"    
"Office-2"    
"work-2"    
"33xxx333"    
"lenovo"    
"Office-1"    
"work-3"    
"22xxx222"    
"dell"

我想要:

"Office-1", "work-1", "11xxx111", "hp"    
"Office-1" "work-3", "22xxx222", "dell"    
"Office-2", "work-2", "33xxx333", "lenovo"

我尝试了jq -S ".[]| .location| group_by(.location),以及像sort_by(.location) 这样的一些其他组合,但它不起作用。我收到错误消息:jq: error (at <stdin>:1): Cannot iterate over string ("Office-1")

我的 JSON 文件示例:

[
  {
    "location": "Office-1",
    "host_name": "work-1",
    "serial_number": "11xxx111",
    "model": "hp"
  },
  {
    "location": "Office-2",
    "host_name": "work-2",
    "serial_number": "33xxx333",
    "model": "lenovo"
  },
  {
    "location": "Office-1",
    "host_name": "work-3",
    "serial_number": "22xxx222",
    "model": "dell"
  }
]

【问题讨论】:

  • 不只是在 jq 中,而是通过管道连接到 | awk '{line==""?line=$0:line=line","$0}NR%4==0{print line; line="";}' | sort -t',' 之类的东西,每四行打印一行,然后对该输出进行排序。
  • 是的,效果很好。我在想我可以使用 jq 但这会做。谢谢

标签: json sorting group-by jq


【解决方案1】:

仅按.location 排序,不进行外部排序:

map( [ .location, .host_name, .serial_number, .model] )
| sort_by(.[0])[]
| map("\"\(.)\"") | join(", ")

", " 符合规定的要求。

如果您希望输出为 CSV,只需将上面 jq 程序中的最后一行替换为 @csv

如果最小化击键是一个目标,那么如果您确定按键始终处于所需的顺序,您可以将第一行替换为 map( [ .[] ] )

【讨论】:

    【解决方案2】:

    您可以要求jq 生成任意格式的字符串。

    curl -L 'http://mylink/ |
    jq -r '.[]| "\"\(.location)\", \"\(.host_name)\", \"\(.serial_number)\", \"\(.model)\""' |
    sort
    

    在双引号内,\" 产生文字双引号,\(.field) 插入字段名称。 -r 选项是生成非 JSON 输出所必需的。

    【讨论】:

    • Q 要求仅按 .location 对结果进行排序,但为了满足排序要求,可以这样写:jq -r '[...] | sort[] 其中 ... 是这里显示的程序 (部分)答案。
    【解决方案3】:

    这将为您提供所需的输出:

    jq -r 'group_by(.location) | .[] | .[] | map(values) | "\"" + join ("\", \"") + "\""'
    

    像这样:

    $ jq -r 'group_by(.location) | .[] | .[] | map(values) | "\"" + join ("\", \"") + "\""' /tmp/so7713.json
    "Office-1", "work-1", "11xxx111", "hp"
    "Office-1", "work-3", "22xxx222", "dell"
    "Office-2", "work-2", "33xxx333", "lenovo"
    

    如果你想把它全部作为一个字符串,那就简单一点:

    $ jq 'group_by(.location) | .[] | .[] | map(values) | join (", ")' /tmp/so7713.json
    "Office-1, work-1, 11xxx111, hp"
    "Office-1, work-3, 22xxx222, dell"
    "Office-2, work-2, 33xxx333, lenovo"
    

    请注意第二个示例中缺少-r

    我觉得必须有更好的方法来处理.[] | .[],但我不知道它是什么(目前)。

    【讨论】:

    • .[]|.[] 可以缩写为.[][],但使用@tripleee 的方法可能在认知上更容易,适当地通过调用sort 来增强。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    相关资源
    最近更新 更多