我有一个bash脚本,旨在解析JSON格式的数据。我从这个论坛的早期查询中了解到,bash不擅长解析JSON,因此打算使用python函数进行解析:
以下是代码段:
#!/bin/bash
set -e
declare -a data_id
declare -a data_tid
function parse_data () {
python <<EOF
import json
parsed = json.loads('''${@}''')
data_id = []
data_tid = []
for child in parsed['params']['children'][0]:
print 'id: %s' % (child['data']['id'])
data_id.append(child['data']['id'])
print 'tid: %s' % (child['data']['tid'])
data_tid.append(child['data']['tid'])
EOF
}
json=$(get_json_output)
parse_data $json
存储在'json'中的数据如下所示:
{
"cid": "1",
"code": null,
"error": null,
"params": {
"children": [
{
"value": {
"id": "0123456789",
"tid": "a.b.c"
},
"data": {
"id": "0987654321",
"tid": "p.q.r"
},
"tid": "m.n.o.p",
}
],
"tid": "m.n.o.p"
},
"reason": null,
"result": true
}
我希望脚本能够将“数据”下的“id”和“tid”字段提取到单独的数组中。但脚本执行失败如下:
root@ubuntu# ./abc.sh
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
TypeError: string indices must be integers
知道什么是错的吗?
答案 0 :(得分:2)
离开[0]
:
for child in parsed['params']['children']:
否则您循环遍历children
列表中第一个条目的键。
或者,如果该列表中只有一个条目,请不要循环,而是直接分配:
child = parsed['params']['children'][0]
print 'id: %s' % (child['data']['id'])
port_id.append(child['data']['id'])
print 'tid: %s' % (child['data']['tid'])
port_tid.append(child['data']['tid'])
答案 1 :(得分:0)
你只指儿童名单的第一项。 所以“孩子”实际上是字典的关键。
你应该从FOR循环中删除[0]
答案 2 :(得分:0)
这一行:
for child in parsed['params']['children'][0]:
...
parsed['params']['children'][0]
不是列表。
将其更改为
for child in parsed['params']['children']:
...
或
# this one only for testing
for child in [parsed['params']['children'][0]]:
...
或
# also for testing
child = parsed['params']['children'][0]
答案 3 :(得分:0)
如果首先编写Python脚本,然后尝试将其嵌入到bash脚本中,您会发现这更容易调试。这是调试版本:
import json, sys
parsed = json.load(sys.stdin)
port_id = []
port_tid = []
for child in parsed['params']['children']:
print 'id: %s' % (child['data']['id'])
port_id.append(child['data']['id'])
print 'tid: %s' % (child['data']['tid'])
port_tid.append(child['data']['tid'])
其次,您的json数据中存在错误。我想你的意思是:
{
"cid": "1",
"code": null,
"error": null,
"params": {
"children": [
{
"value": {
"id": "0123456789",
"tid": "a.b.c"
},
"data": {
"id": "0987654321",
"tid": "p.q.r"
},
"tid": "m.n.o.p"
},
{
"value": {
"id": "0987654321",
"tid": "a.b.c"
},
"data": {
"id": "0123456789",
"tid": "p.q.r"
},
"tid": "m.n.o.p"
}
],
"tid": "m.n.o.p"
},
"reason": null,
"result": true
}
最后,您仍需要将输出加载到Bash数组中。这是我的解决方案:
#!/bin/bash
set -e
parse_ids() { python -c '
import json, sys
parsed = json.load(sys.stdin)
print u"\n".join(c["data"]["id"] for c in parsed["params"]["children"])'
}
parse_tids() { python -c '
import json, sys
parsed = json.load(sys.stdin)
print u"\n".join(c["data"]["tid"] for c in parsed["params"]["children"])'
}
#json=$(get_json_output)
json=$(</dev/stdin)
declare -a port_id
mapfile -t port_id < <(echo "$json" | parse_ids)
echo "${port_id[@]}"
declare -a port_tid
mapfile -t port_tid < <(echo "$json" | parse_tids)
echo "${port_tid[@]}"