我正在寻找一个解决方案,我在构建JSON记录并需要在JQ中生成一些文本,但是将此文本传输到MD5求和函数并将其用作键的值。
echo '{"first": "John", "last": "Big"}' | jq '. | { id: (.first + .last) | md5 }'
通过查看手册和GH问题,我无法弄清楚如何执行此操作,因为函数无法调用shell,并且没有内置提供类似功能的唯一哈希
我正在寻找的一个更好的例子是:
echo '{"first": "John", "last": "Big"}' | jq '. | {first, last, id: (.first + .last | md5) }'
输出:
{
"first": "John",
"last": "Big",
"id": "cda5c2dd89a0ab28a598a6b22e5b88ce"
}
还有一点上下文。我正在创建用于esbulk的NDJson个文件。我需要为每条记录生成一个唯一的密钥。最初,我认为管道外壳是最简单的解决方案,所以我可以轻松地使用sha1sum或其他一些哈希函数,但这看起来比我想象的更具挑战性。
我正在寻找的一个更好的例子是:
echo '[{"first": "John", "last": "Big"}, {"first": "Justin", "last": "Frozen"}]' | jq -c '.[] | {first, last, id: (.first + .last | md5) }'
输出:
{"first":"John","last":"Big","id":"cda5c2dd89a0ab28a598a6b22e5b88ce"}
{"first":"Justin","last":"Frozen","id":"af97f1bd8468e013c432208c32272668"}
答案 0 :(得分:1)
使用tee
允许使用管道,例如:
echo '{"first": "John", "last": "Big"}' |
tee >( jq -r '.first + .last' | md5 | jq -R '{id: .}') |
jq -s add
输出:
{
"first": "John",
"last": "Big",
"id": "cda5c2dd89a0ab28a598a6b22e5b88ce"
}
以下使用while
循环遍历数组的元素,但在每次迭代时调用jq两次。对于在循环中根本不调用jq的解决方案,请参阅本页的其他地方。
echo '[{"first": "John", "last": "Big"}, {"first": "Justin", "last": "Frozen"}]' |
jq -c .[] |
while read -r line ; do
jq -r '[.[]]|add' <<< "$line" | md5 |
jq --argjson line "$line" -R '$line + {id: .}'
done
答案 1 :(得分:1)
环顾四周,我最终发现了这个问题:jq json parser hash the field value这有助于我得到答案:
echo '[{"first": "John", "last": "Big"}, {"first": "Justin", "last": "Frozen"}]' > /tmp/testfile
jsonfile="/tmp/testfile"
jq -c .[] "$jsonfile" | while read -r jsonline ;
do
# quickly parse the JSON line and build the pre-ID out to get md5sum'd and then store that in a variable
id="$(jq -s -j -r '.[] | .first + .last' <<<"$jsonline" | md5sum | cut -d ' ' -f1)"
# using the stored md5sum'd ID we can use that as an argument for adding it to the existing jsonline
jq --arg id "$id" -s -c '.[] | .id = "\($id)"' <<<"$jsonline"
done
{"first":"John","last":"Big","id":"467ffeee8fea6aef01a6ffdcaf747782"}
{"first":"Justin","last":"Frozen","id":"fda76523d5259c0b586441dae7c2db85"}
答案 2 :(得分:0)
jq
+ md5sum
技巧:
json_data='{"first": "John", "last": "Big"}'
jq -r '.first + .last| @sh' <<<"$json_data" | md5sum | cut -d' ' -f1 \
| jq -R --argjson data "$json_data" '$data + {id: .}'
示例输出:
{
"first": "John",
"last": "Big",
"id": "f9e1e448a766870605b863e23d3fdbd8"
}
答案 3 :(得分:0)
这是重述问题的有效解决方案。无论数组的长度如何,总共只有两次调用jq:
json='[{"first": "John", "last": "Big"}, {"first": "Justin", "last": "Frozen"}]'
echo "$json" |
jq -c '.[] | [.[]] | add' |
while read -r line ; do echo "$line" | md5 ; done |
jq -s -R --argjson json "$json" 'split("\n")
| map(select(length>0))
| . as $in
| reduce range(0;length) as $i ($json; .[$i].id = $in[$i])'
这会产生一个数组。只需在最后添加|.[]
即可生成元素流。
或者更简洁一点,目标是每行发送一个对象而不在循环中调用jq:
jq -c --slurpfile md5 <(jq -c '.[] | [.[]] | add' <<< "$json" |
while read -r line ; do printf '"%s"' $(md5 <<< "$line" ) ; done) \
'[., $md5] | transpose[] | .[0] + {id: .[1]}' <<< "$json"
我需要为每条记录生成一个唯一的密钥。
因此,根据每个完整的JSON对象(或更一般地说,整个JSON值)来计算摘要是有意义的,即使用jq -c ‘.[]’