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


当前回答

这是pythonpy的一个很好的用例:

curl 'http://twitter.com/users/username.json' | py 'json.load(sys.stdin)["name"]'

其他回答

使用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']);"

YAML处理器yq

考虑使用yq进行JSON处理。 yq是一个轻量级、可移植的命令行YAML处理器(JSON是YAML的一个子集)。 语法类似于jq。

输入

{
  "name": "Angel",
  "address": {
    "street": "Stairway to",
    "city": "Heaven"
  }
}

用法举例1

yq e ` .name ` $FILE

Angel

用法举例二

yq有一个很好的内置特性,可以使JSON和YAML成为grep-able

yq——输出格式道具$FILE

name = Angel
address.street = Stairway to
address.city = Heaven

你问我怎么搬起石头砸自己的脚,我来提供弹药:

curl -s 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^text/ {print $2}'

您可以使用tr -d '{}'而不是sed。但是把它们完全排除在外似乎也能达到预期的效果。

如果想去掉外部的引号,可以通过sed 's/\(^"\|"$\)//g'输出上述结果

我认为其他人已经敲响了足够的警钟。我会拿着手机等着叫救护车。准备好就开火。

使用PHP CLI解析JSON

这可以说是跑题了,但是由于优先级的原因,如果不提到我们值得信赖和忠诚的PHP,这个问题仍然是不完整的,对吗?

它使用相同的示例JSON,但让我们将其分配给一个变量以减少模糊性。

export JSON='{"hostname":"test","domainname":"example.com"}'

对于PHP来说,它使用了file_get_contents和PHP://stdin流包装器。

echo $JSON | php -r 'echo json_decode(file_get_contents("php://stdin"))->hostname;'

或者使用fgets和已经在CLI常量STDIN中打开的流。

echo $JSON | php -r 'echo json_decode(fgets(STDIN))->hostname;'

这里有一种使用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
        }
    }
}'