根据模式和异常情况查找并替换内部字符串

根据模式和异常情况查找并替换内部字符串

我有一个返回一些键值对的 JSON 字符串,但如果该值是数字,它不会用双引号将其括起来,因此我的 JSON 解析不适​​用于这些情况。

我的想法是通过搜索和替换它找到的任何出现的地方来操作字符串::"除非 : 后面跟着一个左大括号 {

我还需要在末尾关闭双引号,因此我需要找到一种方法来查找任何 0-9 后跟逗号,并将该逗号替换为",

我想我需要 SED 来搜索/替换,但我对 SED 和 RegEx 很陌生,所以不知道如何开始,特别是省略它找到的地方"{并使用 RegEx 来查找[0-9],

示例 JSON 字符串如下所示:

{"data":{"project":{"issue":{"session":{"id":"625fdv6b95e232f08d6cy2686624f315","createdAt":1539849060000,"buildVersionId":"75492373","sdk":{"display":"1.11.1"},"os":{"platform":"unknown","modified":false},"memory":{"free":853000192,"used":1896611840},"storage":{"free":241791528960,"used":14197940224},"device":{"architecture":"arm64","manufacturer":"Samsung"}}}}}}

更改后所需的完成 JSON 如下所示:

{"data":{"project":{"issue":{"session":{"id":"625fdv6b95e232f08d6cy2686624f315","createdAt":"1539849060000","buildVersionId":"75492373","sdk":{"display":"1.11.1"},"os":{"platform":"unknown","modified":false},"memory":{"free":"853000192","used":"1896611840"},"storage":{"free":"241791528960","used":"14197940224"},"device":{"architecture":"arm64","manufacturer":"Samsung"}}}}}}

几乎相同的事情,但现在每个数字都有双引号。

答案1

怎么样

sed 's/:\([0-9]*\)\([,}]\)/:"\1"\2/g' inp >out
  • s/:\([0-9]*\)\([,}]\)- 搜索:后跟数字,后跟,}。将数字放入 capture \1,将,or}放入 \2。
  • /:"\1"\2/g- 替换为 ,:"然后捕获 \1 (数字),然后是",然后捕获 \2 (原始后缀字符)

例子

$ cat inp
{"data":{"project":{"issue":{"session":{"id":"625fdv6b95e232f08d6cy2686624f315","createdAt":1539849060000,"buildVersionId":"75492373","sdk":{"display":"1.11.1"},"os":{"platform":"unknown","modified":false},"memory":{"free":853000192,"used":1896611840},"storage":{"free":241791528960,"used":14197940224},"device":{"architecture":"arm64","manufacturer":"Samsung"}}}}}}
$ sed 's/:\([0-9]*\)\([,}]\)/:"\1"\2/g' inp >out
$ cat desired
{"data":{"project":{"issue":{"session":{"id":"625fdv6b95e232f08d6cy2686624f315","createdAt":"1539849060000","buildVersionId":"75492373","sdk":{"display":"1.11.1"},"os":{"platform":"unknown","modified":false},"memory":{"free":"853000192","used":"1896611840"},"storage":{"free":"241791528960","used":"14197940224"},"device":{"architecture":"arm64","manufacturer":"Samsung"}}}}}}
$ diff out desired
$

答案2

我采用了不同的方法,没有修改 JSON 数据,而是修改了对数值的 grep 操作,而不是查找双引号,如下所示:

buildVersionId=`echo $jsonData | grep -m1 -oP '"buildVersionId"\s*:\s*\K[^"]+"'`

,"然后我删除末尾的最后 2 个字符( )以仅获取实际数字:

buildVersionId=${buildVersionId::${#buildVersionId}-2}

答案3

jq -c '(.. | select(numbers)) |= tostring' file >newfile

jq命令会将 JSON 文档中的所有数字转换为字符串,无论这些数字在文档中的哪个位置找到。

输出以“紧凑”形式写入文件newfile

如果您出于某种原因最终将 JSON 文档放在 shell 变量中,data则可以使用

jq -c -n --argjson d "$data" '$d | (.. | select(numbers)) |= tostring' >newfile

相关内容