members.json
があります。{
"took": 670,
"timed_out": false,
"_shards": {
"total": 8,
"successful": 8,
"failed": 0
},
"hits": {
"total": 74,
"max_score": 1,
"hits": [
{
"_index": "2000_270_0",
"_type": "Medical",
"_id": "02:17447847049147026174478:174159",
"_score": 1,
"_source": {
"memberId": "0x7b93910446f91928e23e1043dfdf5bcf",
"memberFirstName": "Uri",
"memberMiddleName": "Prayag",
"memberLastName": "Dubofsky"
}
},
{
"_index": "2000_270_0",
"_type": "Medical",
"_id": "02:17447847049147026174478:174159",
"_score": 1,
"_source": {
"memberId": "0x7b93910446f91928e23e1043dfdf5bcG",
"memberFirstName": "Uri",
"memberMiddleName": "Prayag",
"memberLastName": "Dubofsky"
}
}
]
}
}
bash
スクリプトを使用して解析したいのですが、フィールドmemberId
のリストのみを取得します。
memberIds
-----------
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG
.bashrc
に追加してみました:function getJsonVal() {
if [ \( $# -ne 1 \) -o \( -t 0 \) ]; then
echo "Usage: getJsonVal 'key' < /tmp/file";
echo " -- or -- ";
echo " cat /tmp/input | getJsonVal 'key'";
return;
fi;
cat | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["'$1'"]';
}
そして呼ばれる:
$ cat members.json | getJsonVal "memberId"
しかし、それは投げます:
Traceback (most recent call last):
File "<string>", line 1, in <module>
KeyError: 'memberId'
使用する場合:
$ cat members.json | \
python -c 'import json,sys;obj=json.load(sys.stdin);print obj;'
ネストされた辞書obj
の構造を調べて、元の行が次のようになることを確認できます。
$ cat members.json | \
python -c 'import json,sys;obj=json.load(sys.stdin);print obj["hits"]["hits"][0]["_source"]["'$1'"]';
その「memberId」要素に。このようにして、Pythonをワンライナーとして維持できます。
ネストされた「ヒット」要素に複数の要素がある場合は、次のようにすることができます。
$ cat members.json | \
python -c '
import json, sys
obj=json.load(sys.stdin)
for y in [x["_source"]["'$1'"] for x in obj["hits"]["hits"]]:
print y
'
Chris Downのソリューションは、任意のレベルで(一意の)キーの単一の値を見つけるのに適しています。
複数の値を出力する2番目の例では、1つのライナーで何を試すべきかという限界に達しています。その時点で、bashで処理の半分を行う理由はほとんどなく、完全なPythonソリューション。
Bashでこれを行う別の方法は、 jshon を使用することです。 jshon
を使用した問題の解決策は次のとおりです:
$ jshon -e hits -e hits -a -e _source -e memberId -u < foo.json
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG
-e
オプションは、jsonから値を抽出します。 -a
は配列と-u
は、最終的な文字列をデコードします。
まあ、あなたのキーはオブジェクトのルートにないことは明らかです。このようなものを試してください:
json_key() {
python -c '
import json
import sys
data = json.load(sys.stdin)
for key in sys.argv[1:]:
try:
data = data[key]
except TypeError: # This is a list index
data = data[int(key)]
print(data)' "$@"
}
これには、単に構文をPythonに挿入するだけでなく、破損(またはさらに悪いことに、任意のコード実行)を引き起こす可能性があるという利点があります。
その後、次のように呼び出すことができます。
json_key hits hits 0 _source memberId < members.json
別の選択肢は jq です:
$ cat members.json | jq -r '.hits|.hits|.[]|._source|.memberId'
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG
これがbashソリューションです。
find_members.sh
次の行をファイルに追加して保存します
#!/bin/bash
echo -e "\nmemberIds\n---------"
cat members.json | grep -E 'memberId'|awk '{print$2}' | cut -d '"' -f2
chmod +x find_members.sh
今それを実行します:
$ ./find_members.sh
memberIds
----------------
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG
以下 このスレッド Pythonでjson.toolを使用します。
python -m json.tool members.json | awk -F'"' '/memberId/{print $4}'
deepdiff を使用すると、正確なキーを知る必要はありません。
import json
from deepdiff import DeepSearch
DeepSearch(json.load(open("members.json", "r")), 'memberId', verbose_level=2)['matched_paths'].values()