使用sed分割JSON

时间:2016-05-25 16:48:44

标签: bash sed

在代码上使用sed时:

echo '{"id": 356709, "author": tom, "time": hello, "author2": {"id": 444444, "pain": high}}' | sed -n 's/^.*"id":"\([^"]*\)".*$/\1/p'

为什么它只返回444444而不是第一个id,356709。

感谢所有帮助 感谢

5 个答案:

答案 0 :(得分:1)

假设有效的JSON,这只是

json='{"id": 356709, "author": "tom", "time": "hello", "author2": {"id": 444444, "pain": "high"}}'
echo "$json" | jq '.id'

jq。使用正确的工具完成工作。

答案 1 :(得分:1)

最好使用json解析器来完成这项工作(参见Chepner的答案)。如果您真的想使用sed(或awk),请参阅下文。

使用sed

这会产生第一个ID:

$ cat File
{"id": 356709, "author": tom, "time": hello, "author2": {"id": 444444, "pain": high}}
$ sed -nE 's/"id": ([^,]*),.*$/\n\1/; s/[^\n]*\n//' File
356709

因为sed正则表达式是贪婪的,所以第一个替换命令匹配第一个id。第二个替换命令对于删除第一个id之前的内容是必要的。

工作原理:

  • s/"id": ([^,]*),.*$/\n\1/

    从第一次出现"id:"到行尾,同时将ID号本身保存在第1组中。它用换行符\n替换该行的这一部分,然后是身份证号码\1

    由于sed逐行读取输入,因此新读入的sed模式空间将永远不会包含换行符。因此,我们可以确定使用此命令添加到行的\n将是模式空间中唯一的换行符。

  • s/[^\n]*\n//

    这从行的开头到第一个换行符匹配,并将其全部删除。

使用awk

使用awk获取第一个id(这可能需要GNU awk):

$ awk -F, 'NR>1{print $1; exit}' RS='"id": ' File
356709

使用awk获取所有ID:

$ awk -F, 'NR>1{print $1}' RS='"id": ' File
356709
444444

工作原理: awk一次隐式读取一个记录文件。默认情况下,awk将一行视为记录。出于我们的目的,我们要求它打破每个id的记录。这样做如下:

  • -F,

    这告诉awk使用逗号作为字段分隔符

  • NR>1{print $1}

    这告诉awk在第一个字段之后的所有记录中打印第一个字段。

  • RS='"id": '

    这告诉awk在看到字符串"id":的任何地方分解记录。这样可以确保第一个字段后面的第一个字段为id个数字。

答案 2 :(得分:0)

因为^.*"id":吞下了第一个"id": 356709。 请记住.匹配任何字符,*可以任意次数读取任何字符。

显然,这不是最好的方法,但我无法继续进行,因为我对预期的输出一无所知。

我很想分享关于[ removal of html tags ]使用sed的答案。

答案 3 :(得分:0)

john1024' s answer是目前为止最好的,但对你的字符串非常具体。例如,如果在第一个{之后没有出现换行符,则会失败。这是一个答案,通常会在字符串,json或其他方式中提取存储为"id":number的所有ID。

如何:1。使用tr删除所有空格,2。使用"id":number查找所有grep,然后仅使用grep输出数字。

echo "$json" |
  tr -d ' \t\n\r\f' |
  grep -o '"id":[0-9]\+' |
  grep -o '[0-9]\+'

仅输出第一个ID,将-m1添加到最后一个grep

echo "$json" |
  tr -d ' \t\n\r\f' |
  grep -o '"id":[0-9]\+' |
  grep -m1 -o '[0-9]\+'

答案 4 :(得分:0)

当您认为可以信任示例中的布局时,您可以尝试:

echo '{"id": 356709, "author": tom, "time": hello, "author2": {"id": 444444, "pain": high}}' |
   sed 's/[^,]*id": \([0-9]*\).*/\1/'

echo '{"id": 356709, "author": tom, "time": hello, "author2": {"id": 444444, "pain": high}}' |
   tr "," "\n" | grep -Pom 1 "id.. \K\d*"