Ich habe ein Bash-Skript, das darauf abzielt, die JSON-formatierten Daten zu analysieren. Ich habe aus einer früheren Abfrage in diesem Forum erfahren, dass Bash JSON nicht gut analysieren kann, und beabsichtige daher, eine Python-Funktion zum Parsen zu verwenden:

Das Folgende ist das Code-Snippet:

#!/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

Die in 'json' gespeicherten Daten würden folgendermaßen aussehen:

{
    "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
}

Ich möchte, dass das Skript die Felder 'id' und 'tid' unter 'data' in separate Arrays extrahieren kann. Die Skriptausführung schlägt jedoch wie folgt fehl:

root@ubuntu# ./abc.sh 
Traceback (most recent call last):
  File "<stdin>", line 7, in <module>
TypeError: string indices must be integers

Irgendeine Idee, was los ist?

2
Maddy 5 Dez. 2013 im 17:09

4 Antworten

Beste Antwort

Urlaub vom [0]:

for child in parsed['params']['children']:

Andernfalls durchlaufen Sie die Schlüssel des ersten Eintrags in der Liste children.

Wenn sich in dieser Liste immer nur ein Eintrag befindet, führen Sie alternativ keine Schleife durch, sondern weisen Sie direkt zu:

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'])
2
Martijn Pieters 5 Dez. 2013 im 13:13

Diese Linie:

for child in parsed['params']['children'][0]:
    ...

parsed['params']['children'][0] ist keine Liste.

Ändere es auf entweder

for child in parsed['params']['children']:
    ...

Oder

# this one only for testing
for child in [parsed['params']['children'][0]]:
    ...

Oder

# also for testing
child = parsed['params']['children'][0]
0
jpwagner 5 Dez. 2013 im 13:28

Das Debuggen ist viel einfacher, wenn Sie zuerst das Python-Skript geschrieben und dann versucht haben, es in ein Bash-Skript einzubetten. Hier ist die debuggte Version:

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'])

Zweitens haben Sie einen Fehler in Ihren JSON-Daten. Ich denke du meintest das:

{
    "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
}

Schließlich müssen Sie die Ausgabe noch in Ihre Bash-Arrays laden. Hier ist meine Lösung:

#!/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[@]}"
0
Michael Kropat 5 Dez. 2013 im 13:59

Sie beziehen sich nur auf das erste Element der Kinderliste. "Kind" ist also eigentlich der Schlüssel des Wörterbuchs.

Sie sollten die [0] aus der FOR-Schleife entfernen

0
le_vine 5 Dez. 2013 im 13:16