我应该如何使用 sed 命令将 JSON 文件中的数字替换为其 MD5 哈希值?

我应该如何使用 sed 命令将 JSON 文件中的数字替换为其 MD5 哈希值?

我有一个 JSON 格式的大日志文件,其中包含一行,如下例所示:

{"data_1":210,"target_number":1096748811,"extra_data":66}
{"data_1":0,"target_number":7130881445,"extra_data":56}
{"data_1":1712,"target_number":1098334917,"extra_data":48}
{"data_1":0,"target_number":3062674667,"extra_data":54}
{"data_1":53,"target_number":5110609228,"extra_data":246}

我想target_number用整个文件中的 MD5 哈希值替换 的值。

我正在尝试使用sed以下基本语法的命令:

sed -i 's/target_number/target_number_md5/' input.log

预期输出(对于上例中的第一个条目)是:

{"data_1":210,"target_number":620e25e6f054992308c564cb883e4940,"extra_data":66}

答案1

以下命令使用磨坊主( mlr) 来解析 JSON 输入(Miller 版本 6 或更高版本应使用--jsonl--json读取“JSON 行”)。然后它使用put子命令来修改键的值target_number。修改是通过openssl md5使用标准输入上传递的原始值进行调用来完成的。然后,我们通过从响应中删除除 MD5 哈希值之外的所有内容来清理生成的字符串。

mlr --json put '
    $target_number = system("printf \"" . $target_number . "\" | openssl md5");
    $target_number = sub($target_number, ".*= ", "")' file

如果您想使用md5sumGNU coreutils,请将openssl md5上面的替换为md5sum --tag.

通过使用md5实用程序(通常在 BSD 系统上找到),我们可以避免printf管道:

mlr --json put '
    $target_number = system("md5 -s \"" . $target_number . "\"");
    $target_number = sub($target_number, ".*= ", "")' file

鉴于问题中的示例,上述每个命令的输出如下:

{ "data_1": 210, "target_number": "620e25e6f054992308c564cb883e4940", "extra_data": 66 }
{ "data_1": 0, "target_number": "f83d74be3dcb71d53263aefdf08203a9", "extra_data": 56 }
{ "data_1": 1712, "target_number": "56ae797ad2c16813d1a6168d28b58d89", "extra_data": 48 }
{ "data_1": 0, "target_number": "81394a193503036fad53b8a9d6ca2456", "extra_data": 54 }
{ "data_1": 53, "target_number": "6f01490a5dc694e51a69b79f7dd21c24", "extra_data": 246 }

由于 MD5 哈希值是字符串,而不是十进制数字,因此它们会作为字符串插入到生成的 JSON 文档中。

mlr如果您使用其选项,Miller 可以用生成的文档替换输入文件(即进行“就地”编辑)-I

target_number请注意,上面的每个命令都在调用中使用原始值system()而不对其进行清理,这样做会构成代码注入漏洞。

答案2

解决类似的问题,我发现了这个问题。提供的解决方案对我来说不太有效,因为我想在没有循环的情况下解决它。

下面是如何在没有循环的情况下解决问题的概念证明:

sed -E 's/(.*target_number":)([0-9]+)(.*)/echo "\1$(echo -n \2 | md5sum)\3"/e;s/  -//' "$inputFile"
  • -E:使用扩展正则表达式而不是基本正则表达式。
  • /e:该命令允许将 shell 命令的输入通过管道传送到模式空间。

有关更多详细信息,请检查此来源:https://www.gnu.org/software/sed/manual/sed.html

答案3

我自己找到了答案。

cat $inputFile | grep -Po '(?<="target_number":)[^,"]+' | while read i ; do
    sed -i "s/$i/$(echo -n $i | md5sum | cut -f 1 -d ' ')/g" $outputFile
done

相关内容