json - 使用 Unix 工具解析 JSON

标签 json bash parsing jq

我正在尝试解析从 curl 请求返回的 JSON,如下所示:

curl 'http://twitter.com/users/username.json' |
    sed -e 's/[{}]/''/g' | 
    awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'

上面将JSON拆分为字段,例如:

% ...
"geo_enabled":false
"friends_count":245
"profile_text_color":"000000"
"status":"in_reply_to_screen_name":null
"source":"web"
"truncated":false
"text":"My status"
"favorited":false
% ...

如何打印特定字段(由 -v k=text 表示)?

最佳答案

有许多专门设计用于从命令行操作 JSON 的工具,并且比使用 Awk 更容易和更可靠,例如 jq :

curl -s 'https://api.github.com/users/lambda' | jq -r '.name'

您也可以使用系统上可能已经安装的工具来执行此操作,例如使用 json module 的 Python ,因此避免了任何额外的依赖性,同时仍然享有适当的 JSON 解析器的好处。以下假设您想要使用 UTF-8,原始 JSON 应该使用 UTF-8 进行编码,大多数现代终端也使用 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/Single Unix Specification shell是一种非常有限的语言,它不包含表示序列(列表或数组)或关联数组(在其他一些语言中也称为哈希表、映射、字典或对象)的工具。这使得在可移植 shell 脚本中表示解析 JSON 的结果有些棘手。有somewhat hacky ways to do it , 但如果键或值包含某些特殊字符,它们中的许多可能会中断。

Bash 4 及更高版本、zsh 和 ksh 支持数组和关联数组,但这些 shell 并非普遍可用(由于从 GPLv2 到 GPLv3,macOS 在 Bash 3 停止更新 Bash,而许多 Linux 系统不支持'开箱即用地安装了 zsh)。您可能可以编写一个可以在 Bash 4 或 zsh 中运行的脚本,其中之一在当今大多数 macOS、Linux 和 BSD 系统上都可用,但是很难编写适用于这种情况的 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 key ,所以我转而使用GitHub API,无需 API key 即可轻松使用。原始问题的第一个答案是:

curl 'http://twitter.com/users/username.json' | jq -r '.text'

关于json - 使用 Unix 工具解析 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56470006/

相关文章:

json - 使用 javax.json 从 JSON 字符串到 Java 对象

python - 如何在 python 中的 json.load 期间编辑/重命名键?

bash - 在 Bash 中使用带 bc 的负指数

微分方程的 Python 解析器 : syntax errors with ast and sympify

c - 创建 AST 后进行语义检查

java - Gson只能从JSON正确解析一个对象?

java - HSSFCell 读取空错误?

Bash 脚本 : No such file or directory when defining variable via source vars. txt

bash - 在 Bash 中打印作为基本拉丁语一部分的 unicode 十六进制代码作为符号

c# - 不同类的大量命令行参数