有许多专门设计用于从命令行操作 JSON 的工具,并且比使用 Awk 更容易、更可靠,例如jq:
curl -s 'https://api.github.com/users/lambda' | jq -r '.name'
您还可以使用系统上可能已安装的工具来执行此操作,例如使用 Pythonjson module,从而避免任何额外的依赖关系,同时仍然拥有适当的 JSON 解析器的好处。以下假设您想要使用 UTF-8,原始 JSON 应该使用 UTF-8 进行编码,并且大多数现代终端也使用这种编码:
Python 3:
curl -s 'https://api.github.com/users/lambda' | \
python3 -c "import sys, json; print(json.load(sys.stdin)['name'])"
Python 2:
export PYTHONIOENCODING=utf8
curl -s 'https://api.github.com/users/lambda' | \
python2 -c "import sys, json; print json.load(sys.stdin)['name']"
经常问的问题
为什么不采用纯 shell 解决方案?
标准POSIX/单一 Unix 规范 shell是一种非常有限的语言,不包含表示序列(列表或数组)或关联数组(在某些其他语言中也称为哈希表、映射、字典或对象)的工具。这使得在可移植 shell 脚本中表示解析 JSON 的结果有些棘手。有有点古怪的方法,但如果键或值包含某些特殊字符,其中许多可能会中断。
Bash 4 及更高版本、zsh 和 ksh 支持数组和关联数组,但这些 shell 并非普遍可用(由于从 GPLv2 更改为 GPLv3,macOS 在 Bash 3 上停止更新 Bash,而许多 Linux 系统没有zsh 开箱即用)。您可以编写一个可以在 Bash 4 或 zsh 中运行的脚本,其中一个可以在当今的大多数 macOS、Linux 和 BSD 系统上使用,但是编写适用于这样的 shell 的 shebang 行是很困难的。多语言脚本。
最后,在 shell 中编写一个成熟的 JSON 解析器将是一个足够重要的依赖项,您不妨使用 jq 或 Python 等现有依赖项来代替。要想实现良好的实现,不会是一行,甚至是五行的小片段。
为什么不使用 awk、sed 或 grep?
可以使用这些工具从具有已知形状并以已知方式格式化的 JSON 中进行一些快速提取,例如每行一个键。其他答案中有几个对此建议的示例。
然而,这些工具是为基于行或基于记录的格式而设计的;它们不是为递归解析具有可能的转义字符的匹配分隔符而设计的。
因此,这些使用 awk/sed/grep 的快速而肮脏的解决方案可能很脆弱,并且如果输入格式的某些方面发生变化(例如折叠空格,或向 JSON 对象添加额外的嵌套级别,或内部的转义引号),就会中断。一个字符串。一个足够强大、能够在不中断的情况下处理所有 JSON 输入的解决方案也将相当大和复杂,因此与添加另一个依赖项没有太大不同jq
或Python。
我之前曾处理过由于 shell 脚本中的输入解析不佳而导致大量客户数据被删除的情况,因此我从不推荐快速而肮脏的方法,因为这样可能会很脆弱。如果您正在进行一些一次性处理,请参阅其他答案以获取建议,但我仍然强烈建议仅使用现有的经过测试的 JSON 解析器。
历史笔记
这个答案最初推荐jsawk,它应该仍然有效,但使用起来比jq
,并且依赖于安装的独立 JavaScript 解释器,该解释器比 Python 解释器不太常见,因此上面的答案可能更可取:
curl -s 'https://api.github.com/users/lambda' | jsawk -a 'return this.name'
这个答案最初也使用了问题中的 Twitter API,但该 API 不再起作用,因此很难复制示例进行测试,并且新的 Twitter API 需要 API 密钥,因此我转而使用 GitHub API无需 API 密钥即可轻松使用。原始问题的第一个答案是:
curl 'http://twitter.com/users/username.json' | jq -r '.text'