从JSON中查找键的值

27

我想从这个JSON单行中提取出"id"键。

我相信可以用grep完成,但是我不确定正确的方法。

如果有不需要依赖的更好的方法,我会很感兴趣。

这是我的示例输出:

{
  "data": {
    "name": "test",
    "id": "4dCYd4W9i6gHQHvd",
    "domains": ["www.test.domain.com", "test.domain.com"],
    "serverid": "bbBdbbHF8PajW221",
    "ssl": null,
    "runtime": "php5.6",
    "sysuserid": "4gm4K3lUerbSPfxz",
    "datecreated": 1474597357
  },
  "actionid": "WXVAAHQDCSILMYTV"
}


这可能会对你有所帮助:https://dev59.com/3HI-5IYBdhLWcg3wO1vl - deathyr
1
尝试使用 grep -o -P '"id":.*?",' json.file |sed 's/"\|,//g' 命令,这应该会有所帮助...但如果您使用一些json感知工具会更好。 - P....
@BenjaminW:data:的内容不应该用[ ]括起来吗? - Inian
您可以查找一些问答:https://dev59.com/3HI-5IYBdhLWcg3wO1vl,https://dev59.com/vWIj5IYBdhLWcg3wOCyS,http://unix.stackexchange.com/questions/121718/how-to-parse-json-with-shell-scripting-in-linux - dkb
5个回答

71

如果你有一个能够执行Perl兼容正则表达式(PCRE)的grep:

$ grep -Po '"id": *\K"[^"]*"' infile.json
"4dCYd4W9i6gHQHvd"
  • -P 启用 PCRE
  • -o 只保留匹配的内容
  • "id": * 匹配 "id" 和任意数量的空格
  • \K 抛弃其左边所有内容 ("可变长正向后查找")
  • "[^"]*" 匹配两个引号之间的所有非引号字符

如果你的 grep 不能做到这一点,你可以使用

$ grep -o '"id": *"[^"]*"' infile.json | grep -o '"[^"]*"$'
"4dCYd4W9i6gHQHvd"

这个命令两次使用了grep。第一个命令的结果是"id": "4dCYd4W9i6gHQHvd";第二个命令删除了除一对括号和它们之间非括号字符以外的所有内容,在字符串末尾锚定 ($)。

但是,正如指出的那样,您不应该使用grep来完成此操作,而是应该使用可以解析JSON的工具,例如jq

$ jq '.data.id' infile.json
"4dCYd4W9i6gHQHvd"

这只是对data对象中的id键的简单过滤器。为了去掉双引号,您可以使用-r(“原始输出”)选项:

$ jq -r '.data.id' infile.json
4dCYd4W9i6gHQHvd

jq 也可以将你的 JSON 数据整齐地打印出来:

$ jq . infile.json
{
  "data": {
    "name": "test",
    "id": "4dCYd4W9i6gHQHvd",
    "domains": [
      "www.test.domain.com",
      "test.domain.com"
    ],
    "serverid": "bbBdbbHF8PajW221",
    "ssl": null,
    "runtime": "php5.6",
    "sysuserid": "4gm4K3lUerbSPfxz",
    "datecreated": 1474597357
  },
  "actionid": "WXVAAHQDCSILMYTV"
}

2
@BenjaminW。谢谢!在这种情况下使用grep将非常完美。这个命令是 grep -o '"id": *"[^"]*"' test.txt | grep -o '"[^"]*"$'。我该如何去掉引号,只留下ID? - petebocken
3
你需要将第一个命令中的最后一个引号和第二个命令中的第一个和最后一个引号都删掉:grep -o '"id": *"[^"]*' test.txt | grep -o '[^"]*$'。这样做可以使命令正常运行。 - Benjamin W.
1
@BenjaminW。我尝试了几次修改,但不知何故始终没找到正确的方法来移除它。这个方案完美地解决了问题,谢谢! - petebocken
1
@BenjaminW。我尝试了使用2个grep的解决方案,它起作用了 :) 干杯 - Salil Lambay
非常感谢@BenjaminW。这个grep porn节省了我几个小时的手动工作。在Mac Catalina的本地grep中运行良好! - BhaveshDiwan
显示剩余4条评论

10
只需将数据导入jq并按键选择。
"data": {
    "name": "test",
    "id": "4dCYd4W9i6gHQHvd",
    "domains": [
      "www.test.domain.com",
      "test.domain.com"
    ],
    "serverid": "bbBdbbHF8PajW221",
    "ssl": null,
    "runtime": "php5.6",
    "sysuserid": "4gm4K3lUerbSPfxz",
    "datecreated": 1474597357
  },
  "actionid": "WXVAAHQDCSILMYTV"
} | jq '.data.id'     

# 4dCYd4W9i6gHQHvd

点此查看教程


8

我发现最好使用Python,因为它可以原生地处理JSON,并且现在大多数系统都预装Python,而不像jq:

$ python -c 'import sys, json; print(json.load(sys.stdin)["data"]["id"])' < infile.json
4dCYd4W9i6gHQHvd

2
喜欢这个答案,因为它使用了现有的资源。仅仅安装更多东西来解决这样的问题太容易了。非常简单,但常被忽略的方法! - kmjb
最佳且简便的解决方案。 - Vovan
这也可以通过 curl 请求进行管道传输,如下所示:curl https://jsonplaceholder.typicode.com/todos/1 | python -c 'import sys, json; print(json.load(sys.stdin)["title"])',并且适用于 Python v2 和 v3。 - Ibrahim.H

5
没有 pythonjqawksed,只有 GNU grep
#!/bin/bash
json='{"data": {"name": "test", "id": "4dCYd4W9i6gHQHvd", "domains": ["www.test.domain.com", "test.domain.com"], "serverid": "bbBdbbHF8PajW221", "ssl": null, "runtime": "php5.6", "sysuserid": "4gm4K3lUerbSPfxz", "datecreated": 1474597357}, "actionid": "WXVAAHQDCSILMYTV"}' 
        
echo $json | grep -o '"id": "[^"]*' | grep -o '[^"]*$'

这里已测试并工作正常:https://ideone.com/EG7fv7

来源:https://brianchildress.co/parse-json-using-grep


它是起作用的,但唯一的问题出现在将 curl 的输出传输到 grep 时,因为 curl 使用 stderr 而不是 stdout 输出结果,我们必须从 stderr 进行管道传输(使用 2>&1),就像这样:curl https://jsonplaceholder.typicode.com/todos/1 2>&1 | grep -o '"title": "[^"]*' | grep -o '[^"]*$' - Ibrahim.H

0

$ grep -oP '"id": *"\K[^"]*' infile.json

4dCYd4W9i6gHQHvd

希望这对所有人都有效。因为这对我来说可以打印出不带引号的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接