在bash脚本中使用python函数-解析JSON
我有一个bash脚本,旨在解析JSON格式的数据。我从本论坛上的一个早期查询中了解到,bash不擅长解析JSON,因此打算使用python函数进行解析: 以下是代码片段:在bash脚本中使用python函数-解析JSON,python,json,bash,Python,Json,Bash,我有一个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 =
#!/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
我希望脚本能够将“数据”下的“id”和“tid”字段提取到单独的数组中。但是脚本执行失败,如下所示:
root@ubuntu# ./abc.sh
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
TypeError: string indices must be integers
root@ubuntu#//abc.sh
回溯(最近一次呼叫最后一次):
文件“”,第7行,在
TypeError:字符串索引必须是整数
知道怎么了吗 离开
[0]
:
for child in parsed['params']['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'])
您所指的只是儿童列表的第一项。 所以“child”实际上是字典的关键 您应该从FOR循环中删除[0]这一行:
for child in parsed['params']['children'][0]:
...
parsed['params']['children'][0]
不是列表
把它改成两个
for child in parsed['params']['children']:
...
或
或
如果您首先编写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数据中有一个bug。我想你的意思是:
{
"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[@]}"
#/bin/bash
set-e
parse_id(){python-c'
导入json,sys
parsed=json.load(sys.stdin)
打印u“\n”.join(c[“数据”][“id”]用于解析的c[“参数”][“子项”])”
}
parse_tids(){python-c'
导入json,sys
parsed=json.load(sys.stdin)
打印u“\n”.join(c[“数据”][“tid”]在解析的[“参数”][“子项”]中用于c)
}
#json=$(获取json输出)
json=$(在调用函数时尝试添加引号:parse_data“$json”
JSON有一个问题:键“value”、“data”和“tid”都在同一个对象中出现多次。这不起作用。@RemcoGerlich:我已经更正了那里缺少的逗号;可能是一个拙劣的复制粘贴。我删除了额外的键。没有用Python编写整个脚本有令人信服的原因吗?@chepner:task要求用bash编写脚本。我观察到,虽然打印效果很好,但这些值并没有附加到数组data_id和data_tid中。数组大小显示为零。@Maddy:你希望Python列表知道你的bash数组吗?那根本不起作用。子进程没有访问bash变量的权限;你没有o让Python进程写入stdout或stderr,在bash脚本中捕获它并从那里开始。没有出路吗?它们不能在脚本中共存并共享数据吗?不,bash的可扩展性不为人知。Python是作为子进程运行的,它不能访问父进程的内存,无论如何也不能没有显式的消息传递.为什么不把所有的东西都移到Python脚本中呢?这样至少就不需要解决这个问题了。
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'])
{
"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
}
#!/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[@]}"