JQ - 按层次结构解析字段
JQ - parsing field by hierarchy
我有非常大的 json 我想使用 jq 从中提取数据总和。
我正在尝试所有可能的方法,但我想我在这里遗漏了一些东西..
我的 Json 子集:
{"main":
{"0": {"x": {"a":1}, "y": {"number of un-used":{"count":2} , "z":2}},
"1": {"x": {"a":1}, "y": {"number of un-used":{"count":3} , "z":2}},
"2": {"x": {"a":1}, "y": {"number of un-used":{"count":4} , "z":2}},
"3": {"x": {"a":1}, "y": {"no un-used":{"z":3} , "z":2}},
"4": {"x": {"a":1}, "y": {"no un-used":{"z":3} , "z":2}}},
"no-main":
{"0": {"x": {"a":1}, "y": {"number of un-used":{"count":2} , "z":2}},
"1": {"x": {"a":1}, "y": {"number of un-used":{"count":3} , "z":2}},
"2": {"x": {"a":1}, "y": {"number of un-used":{"count":4} , "z":2}},
"3": {"x": {"a":1}, "y": {"no un-used":{"z":3} , "z":2}},
"4": {"x": {"a":1}, "y": {"no un-used":{"z":3} , "z":2}}}}
我想要 "count" - "number of un-used" 的总和,即 "y".
我最成功的一个是:
cat json | jq '.[] | .[].y | .["number of un-used"] | .count'
但结果包含很多 "null" 因为 "number of un-used" 不在所有 "y" 字典中..
可以解决吗?
您可以将零添加到 null 以获得...零。
jq '.[] | .[].y | ."number of un-used" | .count + 0' < input.json
这会生成您要查找的 count
个值的列表,null
个值显示 0
。将它们添加到您的总和中应该不会改变它。
jq
可以在其表达式中进行基本算术运算,但让它在内部计算总和会变得稍微复杂一些。虽然您可以定义一个使用 reduce
的函数,但通过向命令行附加一些内容可能更容易对这些值求和,如下所示:
| awk '{n+=}END{print n}'
当然,有无数种方法可以将数字相加,有些方法比其他方法更难懂。
$ { printf '%s+' $(jq '.[] | .[].y | ."number of un-used" | .count + 0' input.json); echo 0; } | bc
18
由于 JSON 非常大,您可能需要一个总体上非常有效的解决方案,因此值得考虑以下内容:
def sigma(s): reduce s as $x (0; .+$x);
sigam(.[].[].y | .["number of un-used"] | .count)
请注意,这也解决了空值问题。为了使解决方案更加稳健,您还可以加入一些 post-fix ?
。
对于巨大的 JSON,您可能需要一个流式处理解决方案,但这会复杂得多,尽管上述定义仍然适用。
如果 JSON 太大而不适合内存,那么可以使用 jq 的流解析器,如此处所示。
调用
$ jq -n --stream -f program.jq input.json
特别注意“-n”选项。
program.jq
def sigma(s): reduce s as $x (0; .+$x);
sigma(inputs
| select(length==2)
| select(.[0][-3:] == ["y","number of un-used","count"])
| .[1] )
我有非常大的 json 我想使用 jq 从中提取数据总和。
我正在尝试所有可能的方法,但我想我在这里遗漏了一些东西..
我的 Json 子集:
{"main":
{"0": {"x": {"a":1}, "y": {"number of un-used":{"count":2} , "z":2}},
"1": {"x": {"a":1}, "y": {"number of un-used":{"count":3} , "z":2}},
"2": {"x": {"a":1}, "y": {"number of un-used":{"count":4} , "z":2}},
"3": {"x": {"a":1}, "y": {"no un-used":{"z":3} , "z":2}},
"4": {"x": {"a":1}, "y": {"no un-used":{"z":3} , "z":2}}},
"no-main":
{"0": {"x": {"a":1}, "y": {"number of un-used":{"count":2} , "z":2}},
"1": {"x": {"a":1}, "y": {"number of un-used":{"count":3} , "z":2}},
"2": {"x": {"a":1}, "y": {"number of un-used":{"count":4} , "z":2}},
"3": {"x": {"a":1}, "y": {"no un-used":{"z":3} , "z":2}},
"4": {"x": {"a":1}, "y": {"no un-used":{"z":3} , "z":2}}}}
我想要 "count" - "number of un-used" 的总和,即 "y".
我最成功的一个是:
cat json | jq '.[] | .[].y | .["number of un-used"] | .count'
但结果包含很多 "null" 因为 "number of un-used" 不在所有 "y" 字典中..
可以解决吗?
您可以将零添加到 null 以获得...零。
jq '.[] | .[].y | ."number of un-used" | .count + 0' < input.json
这会生成您要查找的 count
个值的列表,null
个值显示 0
。将它们添加到您的总和中应该不会改变它。
jq
可以在其表达式中进行基本算术运算,但让它在内部计算总和会变得稍微复杂一些。虽然您可以定义一个使用 reduce
的函数,但通过向命令行附加一些内容可能更容易对这些值求和,如下所示:
| awk '{n+=}END{print n}'
当然,有无数种方法可以将数字相加,有些方法比其他方法更难懂。
$ { printf '%s+' $(jq '.[] | .[].y | ."number of un-used" | .count + 0' input.json); echo 0; } | bc
18
由于 JSON 非常大,您可能需要一个总体上非常有效的解决方案,因此值得考虑以下内容:
def sigma(s): reduce s as $x (0; .+$x);
sigam(.[].[].y | .["number of un-used"] | .count)
请注意,这也解决了空值问题。为了使解决方案更加稳健,您还可以加入一些 post-fix ?
。
对于巨大的 JSON,您可能需要一个流式处理解决方案,但这会复杂得多,尽管上述定义仍然适用。
如果 JSON 太大而不适合内存,那么可以使用 jq 的流解析器,如此处所示。
调用
$ jq -n --stream -f program.jq input.json
特别注意“-n”选项。
program.jq
def sigma(s): reduce s as $x (0; .+$x);
sigma(inputs
| select(length==2)
| select(.[0][-3:] == ["y","number of un-used","count"])
| .[1] )