首页 > 解决方案 > jq:添加嵌套数字?

问题描述

jq中,如何添加嵌套在流对象中的数字?

例子:

{"game":
    {"player1": {"score": 2}}}
{"game":
    {"player1": {"score": 4}}}

我可以使用两个jq调用添加这些数字:

$ cat foo.json | jq '.game.player1.score' | jq --slurp 'add'
6

怎么可以一jq通电话?

另外,如何分别将两个不同玩家的分数相加?

{"game":
    {"player1": {"score": 2},
     "player2": {"score": 20}}}
{"game": 
    {"player1": {"score": 4},
     "player2": {"score": 40}}}

$ cat foo.json | jq '???'
{"player1": 6, "player2": 60} 

标签: jsonjqaddition

解决方案


首先,这是@OguzIsmail 第一个问题的第一个解决方案的变体。它用于验证泛型函数的有用性:

   def sigma(s): reduce s as $x (0; .+$x);

有了这个,并使用 -n 命令行选项,给定问题的解决方案很简单:

    sigma(inputs.game.player1.score)

第二个问题

同样的通用性:

def sigmas(stream; f):
  reduce stream as $s (null;
      [., ($s | f)] | transpose | map(add));

sigmas(inputs | .game; [.player1.score, .player2.score])
| {player1: .[0], player2: .[1]}

请注意,sigmas这里定义的可以处理任意多个加法。一个更通用的解决方案,避免将总和指定为列表,留给读者作为一个(简单的)练习:-)

jq.jq

通常,通用函数可以包含在“标准 jq 库”中。例如,如果你的实用函数在 ~/.jq/jq.jq 中,那么假设 pwd 没有不同的 jq.jq,你可以写(对于第一个问题的解决方案):

jq -n 'include "jq"; sigma(inputs.game.player1.score)' foo.json

库的强大包含

include为了避免与模块路径相关的困难,有时在orimport指令中指定路径是有意义的,例如:

jq -n 'include "jq" {search: "~/jq"}; ...'

推荐阅读