使用 awk 有条件地对 jq 中的数字求和



编辑:在输入/向自己解释时,我发现了问题。此时发布以供参考。

我有一个包含一些 k8s 计算资源要求的 JSON 文件,我正在尝试分别汇总请求和限制。

$ jq -r '.resources.requests.memory' qauat_resources.json
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
4Gi
$ jq -r '.resources.limits.memory' qauat_resources.json
5153960755200m
5153960755200m
5153960755200m
5153960755200m
5153960755200m
5153960755200m
10307921510400m
10307921510400m
10307921510400m
10307921510400m
10307921510400m
10307921510400m
10307921510400m
10307921510400m
10307921510400m

这适用于总结第一个块:

$ jq -r '.resources.requests.memory' qauat_resources.json | awk '{s+=$1; unit=" GiB"} END {print s unit}'
60 GiB

后者以毫字节为单位输出(不知道为什么,相关的 Github 问题(,将其管道到这个工作得很好(转换为 GiB(:

$ awk '{s+=$1 / (1.074*10^12); unit=" GiB"} END {print s unit}'
115.172 GiB

我担心的是这个问题可能会得到解决,和/或输出将包含混合的 GiB/mB,所以我想这样做:

$ awk '{s>10^5 ? s+=$1/(1.074*10^12) : s+=$1; unit=" GiB"} END {print s unit}'

基本上,如果它是一个非常大的数字(对于 GiB 中的内存要求(,假设它被输出为 mB 并对其进行转换,否则只需添加它。如果我通过它运行第二个块(更少的 END(,我会得到这个。

$ jq -r '.resources.limits.memory' qauat_resources.json 
| awk '{s>10^5 ? s+=$1/(1.074*10^12) : s+=$1; unit=" GiB"} {print s unit}'
5153960755200 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB
5.15396e+12 GiB

所以它没有添加,而是在第一次输出后格式化所有内容。对我来说,这将表明三元将转到第二个语句,除了使用 += 运算符。此外,如果我反转逻辑(<,而不是>(,它会按预期求和。鉴于其中的最小数字肯定大于 10^5 (5153960755200> 10^5(,我假设 awk 不会将其视为 int,所以我用 s+0 强制使用它,但它具有相同的输出。更奇怪的是,如果我将条件更改为 s==0,第一行是正确转换为 GiB,之后的每一行都落到第二条语句。因此,我假设第一个输出被视为等于 0,但一旦将其添加到,情况就不再如此。

我在Mac上使用GNU Awk 5.0.1 in zsh,虽然我愿意使用其他工具,但在这一点上,这是一种求知欲。我也完全有可能只是错过了一些非常明显的东西。

问题很简单,s被初始化为0,所以第一次比较总是<10^5(或任何其他自然数,就此而言(,但紧接着,它将是正确的,所以三元将切换语句。我不应该检查s,而是1美元作为比较。另请注意,您必须使用 +0 强制转换它。最后,我在 gawk 和 MacOS 风格的 nawk 上对此进行了测试;它适用于两者。

awk '{$1+0 > 10^5 ? s+=$1/(1.074*10^12) : s+=$1; unit=" GiB"} {print s unit}'

最新更新