使用命令行工具删除结尾的JSON逗号

时间:2018-11-08 03:13:18

标签: json bash sed

我想从json中删除结尾的逗号,

{
  "key1": "value1",
  "object": {
    "key2": "value2", // <- remove comma
  },
  "key3": "value3", // <- remove comma
}

我想出了

tr -d '\n' | \
sed -E 's:,(\s*}):\1:g' | \
jq .

它可以工作,但是我想在sed中完全了解它。

我想出了

sed -E '/,\s*$/ { N; s:,\s*(\n\s*},?):\1: }'

适用于上述输入,但不适用于

{
  "key1": "value1",
  "object": {
    "key2": "value2",
  },
  "key3": "value3",
  "key4": "value4", // <- remove comma
}

N的形式读取下一行,然后从下一行开始。

// output sed -E '/,\s*$/ { N;l }' using l/look command
{
  "key1": "value1",\n  "object": {$
  "key1": "value1",
  "object": {
    "key2": "value2",\n  },$
    "key2": "value2",
  },
  "key3": "value3",\n  "key4": "value4",$
  "key3": "value3",
  "key4": "value4",
}

更新

添加另一个测试示例:

{
  "key1": "value1",
  "object1": {
    "object2": {
      "key2": "value2"
    },
  },
  "key3": "value3",
}

更新

无论我扔给我什么,它都可以工作。

sed -E -n 'H; x; s:,(\s*\n\s*}):\1:; P; ${x; p}' | \
    sed '1 d'

说明:

sed -E -n 'H; x; P; ${x; p}'

-n 'H; x'可以将每行追加到图案空间中的下一行(最后一行仅用${x; p}打印除外)

s:,(\s*\n\s*}):\1:;

删除模式空间中的尾部逗号。

4 个答案:

答案 0 :(得分:2)

使用保留缓冲区:

sed '/^ *\}/{H;x;s/\([^}]\),\n/\1\n/;b};x;/^ *}/d' input

这只是一次sed练习,我认为sed不是完成这项工作的正确工具。它的末尾也需要换行符,或者文件以}结尾。

答案 1 :(得分:2)

由于输入似乎是JSON的某种扩展,因此您可以使用用于此类扩展的命令行工具。例如:

$ hjson -j < input.txt

或:

$ any-json --input-format=hjson input.txt

两种情况下的输出

{
  "key1": "value1",
  "object": {
    "key2": "value2"
  },
  "key3": "value3"
}

答案 2 :(得分:1)

不是sed的答案,而是(python)解决方案:

# load as python dictionary
d = {
  "key1": "value1",
  "object": {
    "key2": "value2",
  },
  "key3": "value3",
}

import json

json.dumps(d) # valid json string

答案 3 :(得分:0)

这里是GNU awk中的一个。它使用"作为字段分隔符,并从奇数字段中删除[ \n]*}之前的逗号(引号外,对于"escaped \" inside"可能会失败)。将"key4": "value4,}",添加到文件中:

$ cat file
{
  "key1": "value1",
  "object": {
    "key2": "value2",
  },
  "key3": "value3",
  "key4": "value4,}",
}

该脚本将整个文件作为单个记录(RS="^$")处理,因此它可能不适用于大文件:

$ awk '
BEGIN {
    FS=OFS="\""
    RS="^$"
}
{
    for(i=1;i<=NF;i++) {                         # or i+=2 and remove the if
        if(i%2)
            $i=gensub(/,([ \n]*\})/,"\\1","g",$i)
    }
}1' file

输出:

{
  "key1": "value1",
  "object": {
    "key2": "value2"
  },
  "key3": "value3",
  "key4": "value4,}"
}