jq-根据现有值定期将计算值添加到.json文件中
有一个输入文件,其中包含连接到某一特定日期的多个对象。现在是十月四日。但是,每个对象都表示一天中的另一个时间,具有不同的值。文件中的ID和日期始终相同: INPUT.json:jq-根据现有值定期将计算值添加到.json文件中,json,jq,Json,Jq,有一个输入文件,其中包含连接到某一特定日期的多个对象。现在是十月四日。但是,每个对象都表示一天中的另一个时间,具有不同的值。文件中的ID和日期始终相同: INPUT.json: [ { "DATE": "04.10.2017 10:20", "ID":"x", "VALUE_ONE": 20, "VALUE_TWO": 3 }, { "DATE": "04.10.2017 12:50", "ID":"x", "VALUE_ONE
[
{
"DATE": "04.10.2017 10:20",
"ID":"x",
"VALUE_ONE": 20,
"VALUE_TWO": 3
},
{
"DATE": "04.10.2017 12:50",
"ID":"x",
"VALUE_ONE": 40,
"VALUE_TWO": 5
},
{
"DATE": "04.10.2017 14:20",
"ID":"x",
"VALUE_ONE": 10,
"VALUE_TWO": 2
}
]
我现在想做的是计算一天的总价值,并做一些数学计算。在这种情况下,要么加3,要么乘3
结果应添加到“consolidated.json”文件中,该文件每天应包含一个对象。为了确保这一点,这一过程将每天重复
我已对“/”后面的计算步骤进行了注释:
CONSOLIDATED.json:
[
{
"DATE": "02.10.2017",
"VALUE_ONE_TODAY": 40,
"VALUE_ONE_TOTAL": 800,
"VALUE_THREE_TODAY": 5,
"VALUE_THREE_TOTAL": 110
},
{
"DATE": "03.10.2017",
"VALUE_ONE_TODAY": 90,
"VALUE_ONE_TOTAL": 890, // =800+90
"VALUE_THREE_TODAY": 8,
"VALUE_THREE_TOTAL": 134 // = 110 + 3*8
},
{ //this object is new!
"DATE": "04.10.2017",
"VALUE_ONE_TODAY": 70,
"VALUE_ONE_TOTAL": 960, // =890+70
"VALUE_THREE_TODAY": 10,
"VALUE_THREE_TOTAL": 164 // =134 +3*10
}
]
我知道我可以用
[.[]|.VALUE_ONE]|add
及
但我不知道如何将其纳入所需结构,并使用最后一天的总数。
谢谢 这里有一个解决方案:
#!/bin/bash
jq -M --argfile i input.json '
def VALUE_keys: keys[] | select(startswith("VALUE"));
def TODAY_keys: keys[] | select(endswith("TODAY"));
def TODAY_($k): "\($k)_TODAY";
def TOTAL_($k): "\($k)_TOTAL";
def new_totals:
$i
| (map(VALUE_keys)|unique) as $attrs
| reduce (.[]|.DATE |= .[:10]) as $d ({}
; reduce $attrs[] as $a (.
; [$d.DATE, $a] as $p | setpath($p; getpath($p)+$d[$a])
)
)
| keys[] as $date
| [$date, .[$date]] ;
def aggregate($k; $total):
.[TODAY_($k)] = $total
| if $k == "VALUE_THREE"
then .[TOTAL_($k)] += $total * 3
else .[TOTAL_($k)] += $total
end ;
def next_day:
foreach new_totals as [$date, $totals] (
max_by(.DATE)
; if .DATE == $date then empty else . end
| .DATE = $date
| .[TODAY_keys] = 0
| reduce ($totals|keys[]) as $k (.; aggregate($k; $totals[$k]))
)
;
. + [next_day]
' consolidated.json | sponge consolidated.json
new_totals计算input.json总和,返回日期和值数组。根据它生成的样本数据:
[
"04.10.2017",
{
"VALUE_ONE": 70,
"VALUE_TWO": 10
}
]
次日将这些值应用于consolidate.json的最新条目
返回第二天的值。例如
{
"DATE": "04.10.2017",
"VALUE_ONE_TODAY": 70,
"VALUE_ONE_TOTAL": 960,
"VALUE_THREE_TODAY": 0,
"VALUE_THREE_TOTAL": 134,
"VALUE_TWO_TODAY": 10,
"VALUE_TWO_TOTAL": 10
}
请注意,示例输出与示例input.json不一致
数值不同
脚本将此添加到输入中,并使用海绵用新数据更新consolidated.json。请注意,该行
| if .DATE == $date then empty else . end
阻止它添加新日期的数据(如果该日期已存在)。如果有其他保障措施,这是不必要的
还要注意,next_day使用foreach处理input.json包含超过一天的数据的情况。例如,如果input.json的第一个元素是
下一天将生成两个条目:
{
"DATE": "03.12.2017",
"VALUE_ONE_TODAY": 20,
"VALUE_ONE_TOTAL": 910,
"VALUE_THREE_TODAY": 0,
"VALUE_THREE_TOTAL": 134,
"VALUE_TWO_TODAY": 3,
"VALUE_TWO_TOTAL": 3
}
{
"DATE": "04.10.2017",
"VALUE_ONE_TODAY": 50,
"VALUE_ONE_TOTAL": 960,
"VALUE_THREE_TODAY": 0,
"VALUE_THREE_TOTAL": 134,
"VALUE_TWO_TODAY": 7,
"VALUE_TWO_TOTAL": 10
}
这是一个简单的解决方案,为了便于阐述,它使以下假设易于处理: input.json的内容如广告所示,尤其是input.json中的对象日期尚未出现在consolidated.json中; consolidated.json中数组中的最后一个条目具有最近的日期,并且该日期早于input.json中条目的日期 合并.jq 调用 如果您确信这样做是安全的,那么您可以添加:| spineconsolidated.json 输出 添加的条目符合要求,即:
{
"DATE": "04.10.2017",
"VALUE_ONE_TODAY": 70,
"VALUE_ONE_TOTAL": 960,
"VALUE_THREE_TODAY": 10,
"VALUE_THREE_TOTAL": 164
}
不清楚如何计算总共164个值?看起来你在试图建立每天每个值的累积总和。你是如何确定起始金额的?它只是定义为VALUE_ONE[0]=800,还是仅仅来自于以前的调用?jq可以单独做这个计算。。。如果它是从0开始的。如果您能澄清一些细节,这将非常有帮助。数值键之间的具体计算是否固定?某些input.json是否可以引入以前未看到的新值?是在input.json中使用VALUE_TWO和VALUE_TWO。。。在consolidated.json中是故意的还是错误的?也就是说,为什么价值二和价值三。。。当一个键的值显示为非时,键相关?如果在数据的订购和可能的意外再处理方面需要采取任何预防措施,该怎么办?
{
"DATE": "03.12.2017",
"VALUE_ONE_TODAY": 20,
"VALUE_ONE_TOTAL": 910,
"VALUE_THREE_TODAY": 0,
"VALUE_THREE_TOTAL": 134,
"VALUE_TWO_TODAY": 3,
"VALUE_TWO_TOTAL": 3
}
{
"DATE": "04.10.2017",
"VALUE_ONE_TODAY": 50,
"VALUE_ONE_TOTAL": 960,
"VALUE_THREE_TODAY": 0,
"VALUE_THREE_TOTAL": 134,
"VALUE_TWO_TODAY": 7,
"VALUE_TWO_TOTAL": 10
}
def aggregate:
{DATE: (.[0]|.DATE|split(" ")[0]),
VALUE_ONE_TODAY: (map(.VALUE_ONE) | add),
VALUE_TWO_TODAY: (map(.VALUE_TWO) | add)}
;
.[-1] as $previous
| ($i | aggregate
| {DATE,
VALUE_ONE_TODAY,
VALUE_ONE_TOTAL : ($previous.VALUE_ONE_TOTAL + .VALUE_ONE_TODAY),
VALUE_THREE_TODAY : ($previous.VALUE_TWO_TOTAL + .VALUE_TWO_TODAY) }
| .VALUE_THREE_TOTAL = ($previous.VALUE_THREE_TOTAL + 3 * .VALUE_THREE_TODAY) ) as $today
| . + [$today]
jq -f consolidate.jq --argfile i input.json consolidated.json
{
"DATE": "04.10.2017",
"VALUE_ONE_TODAY": 70,
"VALUE_ONE_TOTAL": 960,
"VALUE_THREE_TODAY": 10,
"VALUE_THREE_TOTAL": 164
}