shell-输出值到 md5(加密)函数

shell-out value to md5 (crypto) function

我正在寻找一种解决方案,我正在构建 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"
}

编辑2

以及更多背景信息。我正在创建 NDJson 文件以用于 esbulk。我需要为每条记录生成一个唯一的密钥。最初,我认为输出到 shell 将是最简单的解决方案,因此我可以轻松地使用 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"}

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"
}

使用 tee 允许使用管道,例如:

echo '{"first": "John", "last": "Big"}' |
    tee >( jq -r '.first + .last' | md5 | jq -R '{id: .}') |
    jq -s add

输出:

{
  "first": "John",
  "last": "Big",
  "id": "cda5c2dd89a0ab28a598a6b22e5b88ce"
}

编辑2:

下面使用了一个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

环顾四周,我最终发现了这个: 这有助于我得到以下答案:

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"}

这里是重述问题的有效解决方案。无论数组的长度如何,总共只有两次对 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"

每条记录的不同摘要

I need to generate a unique key for each record.

因此,根据每个完整的 JSON 对象(或更一般地说,整个 JSON 值)计算摘要是有意义的,即使用 jq -c ‘.[]’

我根据我的案例改编了已接受答案的脚本,将其张贴在这里,它可能对某些人有用。

input.json:

{"date":100,"text":"some text","name":"april"}
{"date":200,"text":"a b c","name":"may"}
{"date":300,"text":"some text","name":"april"}

output.json:

{"date":100,"text":"some text","name":"april","id":"4d93d51945b88325c213640ef59fc50b"}
{"date":200,"text":"a b c","name":"may","id":"3da904d79fb03e6e3936ff2127039b1a"}
{"date":300,"text":"some text","name":"april","id":"4d93d51945b88325c213640ef59fc50b"}

bash脚本生成output.json:

cat input.json |
while read -r line ; do
    jq -r '.text' <<< "$line" | md5 |
        jq -c --argjson line "$line" -R '$line + {id: .}' \
        >> output.json
done