我试图解析从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=文本表示)?


当前回答

这里有一种使用AWK的方法:

curl -sL 'http://twitter.com/users/username.json' | awk -F"," -v k="text" '{
    gsub(/{|}/,"")
    for(i=1;i<=NF;i++){
        if ( $i ~ k ){
            print $i
        }
    }
}'

其他回答

这里有一种使用AWK的方法:

curl -sL 'http://twitter.com/users/username.json' | awk -F"," -v k="text" '{
    gsub(/{|}/,"")
    for(i=1;i<=NF;i++){
        if ( $i ~ k ){
            print $i
        }
    }
}'

你可以使用bashJson

它是Python JSON模块的包装器,可以处理复杂的JSON数据。

让我们考虑来自test.json文件的示例JSON数据

{
    "name":"Test tool",
    "author":"hack4mer",
    "supported_os":{
        "osx":{
            "foo":"bar",
            "min_version" : 10.12,
            "tested_on" : [10.1,10.13]
        },
        "ubuntu":{
            "min_version":14.04,
            "tested_on" : 16.04
        }
    }
}

下面的命令从这个示例JSON文件读取数据

./bashjson.sh test.json name

打印:测试工具

./bashjson.sh test.json supported_os osx foo

打印:酒吧

./bashjson.sh test.json supported_os osx tested_on

打印:[10.1,10.13]

更新(2020)

我使用外部工具(例如Python)时遇到的最大问题是,你必须处理包管理器和安装它们的依赖关系。

然而,现在我们有了jq作为一个独立的静态工具,很容易通过GitHub发布和Webi (webinstall.dev/jq)跨平台安装,我建议:

Mac、Linux:

curl -sS https://webi.sh/jq | bash

Windows 10:

curl.exe -A MS https://webi.ms/jq | powershell

小抄:https://webinstall.dev/jq

原(2011)

TickTick是一个用bash编写的JSON解析器(不到250行代码)。

以下是作者在他的文章《想象一个Bash支持JSON的世界》中的片段:

#!/bin/bash
. ticktick.sh

``
  people = {
    "Writers": [
      "Rod Serling",
      "Charles Beaumont",
      "Richard Matheson"
    ],
    "Cast": {
      "Rod Serling": { "Episodes": 156 },
      "Martin Landau": { "Episodes": 2 },
      "William Shatner": { "Episodes": 2 }
    }
  }
``

function printDirectors() {
  echo "  The ``people.Directors.length()`` Directors are:"

  for director in ``people.Directors.items()``; do
    printf "    - %s\n" ${!director}
  done
}

`` people.Directors = [ "John Brahm", "Douglas Heyes" ] ``
printDirectors

newDirector="Lamont Johnson"
`` people.Directors.push($newDirector) ``
printDirectors

echo "Shifted: "``people.Directors.shift()``
printDirectors

echo "Popped: "``people.Directors.pop()``
printDirectors

有一个有趣的工具在现有的答案中还没有涉及到,那就是使用用Go编写的gron,它的口号是Make JSON可greppable!这正是它所做的。

所以从本质上讲,gron将JSON分解为离散的赋值,查看它的绝对“路径”。与jq等其他工具相比,它的主要优点是允许在不知道要搜索的记录是如何嵌套的情况下搜索值,而不会破坏原始的JSON结构

例如,我想从下面的链接搜索'twitter_username'字段,我只是这样做

% gron 'https://api.github.com/users/lambda' | fgrep 'twitter_username'
json.twitter_username = "unlambda";
% gron 'https://api.github.com/users/lambda' | fgrep 'twitter_username' | gron -u
{
  "twitter_username": "unlambda"
}

就这么简单。请注意gron -u (ungron的缩写)如何从搜索路径重新构造JSON。使用fgrep只是为了将搜索过滤到所需的路径,而不是让搜索表达式作为正则表达式计算,而是作为固定字符串(本质上是grep -F)

另一个搜索字符串以查看记录在嵌套结构中的位置的示例

% echo '{"foo":{"bar":{"zoo":{"moo":"fine"}}}}' | gron | fgrep "fine"
json.foo.bar.zoo.moo = "fine";

它还通过-s命令行标志支持JSON流,在这里您可以连续地对输入流进行gron以获得匹配的记录。此外,gron具有零运行时依赖性。你可以下载Linux、Mac、Windows或FreeBSD的二进制文件并运行它。

更多的用法示例和行程可以在官方Github页面-高级用法中找到

至于为什么可以使用gron而不是其他JSON解析工具,请参阅项目页面的作者注释。

为什么我不应该直接使用jq?

Jq非常棒,比gron强大得多,但这种强大带来了复杂性。Gron的目标是使您更容易使用您已经知道的工具,如grep和sed。

使用Python的JSON支持,而不是使用AWK!

就像这样:

curl -s http://twitter.com/users/username.json | \
    python -c "import json,sys;obj=json.load(sys.stdin);print(obj['name']);"

macOS v12.3 (Monterey)删除了/usr/bin/python,因此对于macOS v12.3及更高版本,我们必须使用/usr/bin/python3。

curl -s http://twitter.com/users/username.json | \
    python3 -c "import json,sys;obj=json.load(sys.stdin);print(obj['name']);"