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


当前回答

下面是shell书呆子使用POSIX shell(带local)和egrep的答案:JSON.sh, 4.7 KB。

这个东西有很多测试用例,所以它应该是正确的。它也是可管道的。它用于Bash的包管理器bpkg。

其他回答

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

还有一个非常简单但功能强大的JSON CLI处理工具fx。

例子

使用匿名函数:

echo '{"key": "value"}' | fx "x => x.key"

输出:

value

如果你不传递匿名函数参数→…,代码将自动转换为匿名函数。你可以通过这个关键字访问JSON:

$ echo '[1,2,3]' | fx "this.map(x => x * 2)"
[2, 4, 6]

或者也可以使用点语法:

echo '{"items": {"one": 1}}' | fx .items.one

输出:

1

你可以传递任意数量的匿名函数来减少JSON:

echo '{"items": ["one", "two"]}' | fx "this.items" "this[1]"

输出:

two

您可以使用扩展操作符更新现有JSON:

echo '{"count": 0}' | fx "{...this, count: 1}"

输出:

{"count": 1}

只是简单的JavaScript。没有必要学习新的语法。


fx的后期版本有一个互动模式!-

这是使用大多数发行版上可用的标准Unix工具。它也适用于反斜杠(\)和引号(")。

警告:这并不能接近jq的功能,并且只能用于非常简单的JSON对象。这是在无法安装其他工具的情况下尝试回答最初的问题。

function parse_json()
{
    echo $1 | \
    sed -e 's/[{}]/''/g' | \
    sed -e 's/", "/'\",\"'/g' | \
    sed -e 's/" ,"/'\",\"'/g' | \
    sed -e 's/" , "/'\",\"'/g' | \
    sed -e 's/","/'\"---SEPERATOR---\"'/g' | \
    awk -F=':' -v RS='---SEPERATOR---' "\$1~/\"$2\"/ {print}" | \
    sed -e "s/\"$2\"://" | \
    tr -d "\n\t" | \
    sed -e 's/\\"/"/g' | \
    sed -e 's/\\\\/\\/g' | \
    sed -e 's/^[ \t]*//g' | \
    sed -e 's/^"//'  -e 's/"$//'
}


parse_json '{"username":"john, doe","email":"john@doe.com"}' username
parse_json '{"username":"john doe","email":"john@doe.com"}' email

--- outputs ---

john, doe
johh@doe.com

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

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'输出上述结果

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

我需要在Bash中一些简短的东西,可以在没有依赖的情况下运行,而不是香草Linux LSB和Mac OS的Python 2.7和3,并处理错误,例如,将报告JSON解析错误和丢失的属性错误,而不会抛出Python异常:

json-extract () {
  if [[ "$1" == "" || "$1" == "-h" || "$1" == "-?" || "$1" == "--help" ]] ; then
    echo 'Extract top level property value from json document'
    echo '  Usage: json-extract <property> [ <file-path> ]'
    echo '  Example 1: json-extract status /tmp/response.json'
    echo '  Example 2: echo $JSON_STRING | json-extract status'
    echo '  Status codes: 0 - success, 1 - json parse error, 2 - property missing'
  else
    python -c $'import sys, json;\ntry: obj = json.load(open(sys.argv[2])); \nexcept: sys.exit(1)\ntry: print(obj[sys.argv[1]])\nexcept: sys.exit(2)' "$1" "${2:-/dev/stdin}"
  fi
}