私はカールリクエストから返された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=text
で表される)を印刷するにはどうすればいいですか?
コマンドラインからJSONを操作することを目的として特別に設計されたツールがいくつもあり、Awkを使用するよりもはるかに簡単で信頼性が高くなります。たとえば、 jq
のようになります。
curl -s 'https://api.github.com/users/lambda' | jq -r '.name'
Pythonに json
モジュール を使用するなど、システムにすでにインストールされている可能性があるツールを使用してこれを行うこともできます。そのため、適切なJSONパーサーの恩恵を受けながら余分な依存関係を避けます。以下はUTF-8を使いたいと仮定しています。これはオリジナルのJSONをエンコードする必要があり、最近のほとんどの端末でも使用されています。
Python 2:
export PYTHONIOENCODING=utf8
curl -s 'https://api.github.com/users/lambda' | \
python -c "import sys, json; print json.load(sys.stdin)['name']"
Python 3:
curl -s 'https://api.github.com/users/lambda' | \
python3 -c "import sys, json; print(json.load(sys.stdin)['name'])"
この回答はもともと jsawk を推奨していましたが、これはまだ動作するはずですが、jq
よりも使用するのがやや面倒で、スタンドアロンのJavaScriptインタプリタがインストールされていることに依存します。好ましい:
curl -s 'https://api.github.com/users/lambda' | jsawk -a 'return this.name'
この回答ではもともと質問からTwitter APIを使用していましたが、そのAPIは機能しなくなり、例をコピーしてテストするのが難しくなり、新しいTwitter APIにはAPIキーが必要になり、GitHub APIを使用するようになりました。 APIキーがなくても簡単に使用できます。元の質問に対する最初の回答は次のようになります。
curl 'http://Twitter.com/users/username.json' | jq -r '.text'
特定のキーの値を素早く抽出するために、私は個人的に "grep -o"を使うのが好きです。これは正規表現のマッチだけを返します。たとえば、ツイートから「テキスト」フィールドを取得するには、次のようにします。
grep -Po '"text":.*?[^\\]",' tweets.json
この正規表現はあなたが思う以上に堅牢です。例えば、それは、埋め込まれたコンマとエスケープされた引用符を含む文字列をうまく扱います。アトミックであれば、もう少し作業をして、実際に値を引き出すことが保証されているものを作成できると思います。 (入れ子になっている場合、正規表現ではもちろんできません。)
(文字列の元のエスケープを維持しながら)さらにクリーンにするには、| Perl -pe 's/"text"://; s/^"//; s/",$//'
のようなものを使用できます。 (私はこれを この分析のために に行った。)
あなたが本当のJSONパーサを使うべきだと主張するすべての憎しみに - はい、それは正確さのために不可欠ですが、
grep -o
はPython標準のjson
ライブラリよりも桁違いに速いです。これがjson
が遅いという理由だけかどうかはわかりません(いつかyajlと比較する必要があります)。しかし、原則として、再帰をサポートしなければならないパーサーの代わりに、正規表現は有限状態であり、より最適化可能であるため、より高速であるべきです。この場合、気にしない構造に対して多くのCPU構築ツリーを費やします。 (誰かが適切な(深さ制限の)JSON構文解析を行った有限状態トランスデューサーを書いたなら、それは素晴らしいでしょう!その間、私たちは "grep -o"を持っています。)保守可能なコードを書くために、私はいつも本物の解析ライブラリを使います。 jsawk を試したことはありませんが、うまく動作すれば、それがポイント#1になります。
最後の、より巧妙な解決策:私はPythonのjson
を使い、必要なキーをタブ区切りのカラムに抽出するスクリプトを書きました。それからカラムへの名前付きアクセスを可能にするawk
の周りのラッパーを通してパイプを通します。 ここに:json2tsvとtsvawkスクリプト 。したがって、この例では次のようになります。
json2tsv id text < tweets.json | tsvawk '{print "Tweet " $id " is: " $text}'
このアプローチは#2を扱っていません、単一のPythonスクリプトより非効率的です、そしてそれは少し脆いです:それはawkのフィールド/レコードで区切られた世界観でNiceを再生するために文字列値で改行とタブの正規化を強制します。しかし、それはあなたがgrep -o
よりも正確で、あなたがコマンドラインにとどまることを可能にします。
ここでのいくつかの推奨(特にコメント内)がPythonの使用を示唆していることに基づいて、私は例を見つけないことに失望しました。
それで、ここにいくつかのJSONデータから単一の値を得るための一つの裏書があります。それはあなたが(どこかから)データをパイプインしていると仮定しているので、スクリプトの文脈では役に立つはずです。
echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["hostname"]'
MartinRとBoeckoのリードに従って。
$ curl -s 'http://Twitter.com/users/username.json' | python -mjson.tool
それはあなたに非常にわかりやすい出力を与えるでしょう。とても便利:
$ curl -s 'http://Twitter.com/users/username.json' | python -mjson.tool | grep my_key
あなたは あなたのプラットフォーム用のjq
バイナリをダウンロードすることができます そして(chmod +x jq
)を実行することができます:
$ curl 'https://Twitter.com/users/username.json' | ./jq -r '.name'
Jsonオブジェクトから"name"
属性を抽出します。
jq
ホームページ JSONデータのsed
のようなものです。
Awkの代わりに PythonのJSONサポート を使用してください。
このようなもの:
curl -s http://Twitter.com/users/username.json | \
python -c "import json,sys;obj=json.load(sys.stdin);print obj['name'];"
システムに node がインストールされている場合は、-p
printおよび-e
を JSON.parse
とともに使用して必要な値を取り出すことができます。
JSON文字列{ "foo": "bar" }
を使って "foo"の値を取り出す簡単な例:
$ node -pe 'JSON.parse(process.argv[1]).foo' '{ "foo": "bar" }'
bar
cat
や他のユーティリティにアクセスできるので、これをファイルに使用できます。
$ node -pe 'JSON.parse(process.argv[1]).foo' "$(cat foobar.json)"
bar
JSONを含むURLなど、その他の形式
$ node -pe 'JSON.parse(process.argv[1]).name' "$(curl -s https://api.github.com/users/trevorsenior)"
Trevor Senior
あなたは自分の足を撃つ方法を頼んだ、そして私は弾薬を提供するためにここにいる:
curl -s 'http://Twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^text/ {print $2}'
sed
の代わりにtr -d '{}'
を使用することもできます。しかし、それらを完全に除外しても同様に望ましい効果があるようです。
外側の引用符を取り除きたい場合は、上記の結果をsed 's/\(^"\|"$\)//g'
に渡してください。
私は他人が十分な警告を鳴らしたと思います。私は救急車を呼ぶために携帯電話で待機します。準備ができたら発砲します。
.bash_rcファイルにbash関数を作成します
function getJsonVal () {
python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1))";
}
それから
$ curl 'http://Twitter.com/users/username.json' | getJsonVal "['text']"
My status
$
これは同じ機能ですが、エラーチェックがあります。
function getJsonVal() {
if [ \( $# -ne 1 \) -o \( -t 0 \) ]; then
cat <<EOF
Usage: getJsonVal 'key' < /tmp/
-- or --
cat /tmp/input | getJsonVal 'key'
EOF
return;
fi;
python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1))";
}
$#-ne 1は少なくとも1つの入力を確認し、-t 0はパイプからのリダイレクトを確認します。
この実装のいいところは、入れ子になったjson値にアクセスしてjsonを取得できることです。 =)
例:
$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' | getJsonVal "['foo']['a'][1]"
2
あなたが本当に空想になりたいなら、あなたはかなりデータを印刷することができました:
function getJsonVal () {
python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1, sort_keys=True, indent=4))";
}
$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' | getJsonVal "['foo']"
{
"a": [
1,
2,
3
],
"bar": "baz"
}
TickTick は、bashで書かれたJSONパーサーです(<250行のコード)。
これが彼の記事からの著者の抜粋です。 BashがJSONをサポートする世界を想像してください :
#!/bin/bash
. ticktick.sh
``
people = {
"Writers": [
"Rod Serling",
"Charles Beaumont",
"Richard Matheson"
],
"Cast": {
"Rod Serling": { "Episodes": 156 },
"Martin Landau": { "Episodes": 2 },
"William Shatner": { "Episodes": 2 }
}
}
``
function printDirectors() {
echo " The ``people.Directors.length()`` Directors are:"
for director in ``people.Directors.items()``; do
printf " - %s\n" ${!director}
done
}
`` people.Directors = [ "John Brahm", "Douglas Heyes" ] ``
printDirectors
newDirector="Lamont Johnson"
`` people.Directors.Push($newDirector) ``
printDirectors
echo "Shifted: "``people.Directors.shift()``
printDirectors
echo "Popped: "``people.Directors.pop()``
printDirectors
議論の余地はありませんが、優先順位が支配しているので、この質問は私たちの信頼でき、忠実なPHPについての言及がなければ不完全なままです。
同じサンプルJSONを使用しますが、それを変数に割り当てて、不明瞭さを軽減します。
$ export JSON='{"hostname":"test","domainname":"example.com"}'
今度はPHPのために、 file_get_contents と php:// stdin ストリームラッパーを使用してください。
$ echo $JSON|php -r 'echo json_decode(file_get_contents("php://stdin"))->hostname;'
または fgets およびCLI定数 _ stdin _ ですでに開かれているストリームを使用して指摘したように。
$ echo $JSON|php -r 'echo json_decode(fgets(STDIN))->hostname;'
nジョイ!
ネイティブBashバージョン:バックスラッシュ(\)と引用符( ")でもうまく機能します。
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":"[email protected]"}' username
parse_json '{"username":"john doe","email":"[email protected]"}' email
--- outputs ---
john, doe
[email protected]
Rubyを使ったバージョンと http://flori.github.com/json/
$ < file.json Ruby -e "require 'rubygems'; require 'json'; puts JSON.pretty_generate(JSON[STDIN.read]);"
もっと簡潔に言うと:
$ < file.json Ruby -r rubygems -r json -e "puts JSON.pretty_generate(JSON[STDIN.read]);"
残念ながら、grep
を使ったトップ投票の答えは full のマッチを返しますが、JSONフォーマットが変わらない場合は lookbehind と lookaheadを使うことができます。 目的の値だけを抽出します。
# echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="FooBar":")(.*?)(?=",)'
he\"llo
# echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="TotalPages":)(.*?)(?=,)'
33
# echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="anotherValue":)(.*?)(?=})'
100
私はここで答えのどれも使うことができません。利用可能なjq、シェル配列、宣言、grep -P、先読みおよび先読み、Python、Perl、Ruby、bashなどはありません。残りの回答は、うまく機能しません。 JavaScriptはおなじみのように聞こえましたが、Nescaffeによれば - それもダメです:)たとえ利用可能であっても、私の単純な必要性のために - それらはやり過ぎで遅くなるでしょう。
それでも、私のモデムのjson形式の返信から多くの変数を取得することが私にとって非常に重要です。私は自分のルータで非常にトリミングされたBusyBoxを使ってshでそれをやっています! awkを単独で使用しても問題ありません。区切り文字を設定してデータを読み取るだけです。単一の変数の場合、これですべてです。
awk 'BEGIN { FS="\""; RS="," }; { if ($2 == "login") {print $4} }' test.json
配列がないことを忘れないでください。私はawk内で解析したデータをシェルスクリプトで必要な11個の変数に割り当てなければなりませんでした。私がどこを見ても、それは不可能な使命だと言われていました。それも問題ありません。
私の解決策は簡単です。このコードは、1)質問から.jsonファイルを解析し(実際には、最も支持された回答から実用的なデータサンプルを借りて)、2)awk内からシェル変数を作成します。変数名.
eval $( curl -s 'https://api.github.com/users/lambda' |
awk ' BEGIN { FS="\""; RS="," };
{
if ($2 == "login") { print "Login=\""$4"\"" }
if ($2 == "name") { print "Name=\""$4"\"" }
if ($2 == "updated_at") { print "Updated=\""$4"\"" }
}' )
echo "$Login, $Name, $Updated"
空白の問題はありません。私の使用では、同じコマンドが長い単一行の出力を解析します。 evalが使用されているため、このソリューションは信頼できるデータにのみ適しています。引用符で囲まれていないデータをピックアップするように調整するのは簡単です。膨大な数の変数については、else ifを使用して限界速度の向上を達成できます。配列がないということは明らかに次のことを意味します。しかし、配列が利用可能な場合、このソリューションを適応させるのは簡単な作業です。
@maikel sedの答えはほとんどうまくいきます(しかし私はそれについてコメントできません)。私のきれいにフォーマットされたデータのために - それはうまくいきます。ここで使用されている例ではそれほど重要ではありません(引用符が欠落しているとそれは無視されます)。それは複雑で修正が困難です。さらに、11個の変数を抽出するために11回呼び出す必要はありません。どうして? 100ループで9つの変数を抽出しました。sed関数には48.99秒かかり、私の解には0.91秒かかりました。公平ではない? 9つの変数を1回だけ抽出する:0.51対0.02秒。
Powershellがクロスプラットフォームになったので、かなり直感的で非常に単純であることがわかったので、私はそこから抜け出すことを考えました。
curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json
ConvertFrom-JsonはJSONをPowershellカスタムオブジェクトに変換するので、それ以降は簡単にプロパティを操作できます。たとえば 'id'プロパティだけが必要な場合は、次のようにします。
curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json | select -ExpandProperty id
Bash内から全部を起動したい場合は、次のように呼び出す必要があります。
powershell 'curl -s "https://api.github.com/users/lambda" | ConvertFrom-Json'
もちろん、カールせずにそれを実行する純粋なPowershellの方法があります。
Invoke-WebRequest 'https://api.github.com/users/lambda' | select -ExpandProperty Content | ConvertFrom-Json
最後に、カスタムオブジェクトをJSONに変換する 'ConvertTo-Json'もあります。これが例です:
(New-Object PsObject -Property @{ Name = "Tester"; SomeList = @('one','two','three')}) | ConvertTo-Json
これは、次のようにNice JSONを生成します。
{
"Name": "Tester",
"SomeList": [
"one",
"two",
"three"
]
}
確かに、UNIX上でWindowsシェルを使用するのは多少不愉快ですが、Powershellはいくつかの点で本当に優れており、JSONとXMLの解析はそれらのいくつかです。このクロスプラットフォーム版のGitHubページ https://github.com/PowerShell/PowerShell
jshon
を使用できます。
curl 'http://Twitter.com/users/username.json' | jshon -e text
phpがある場合:
php -r 'var_export(json_decode(`curl http://Twitter.com/users/username.json`, 1));'
例えば:
jsonに国isoコードを提供するリソースがあります: http://country.io/iso3.json
curl http://country.io/iso3.json
しかし、それはあまり便利ではなく、読みにくいです、jsonをより良く解析し、読みやすい構造を見る:
php -r 'var_export(json_decode(`curl http://country.io/iso3.json`, 1));'
このコードは次のようなものを出力します:
array (
'BD' => 'BGD',
'BE' => 'BEL',
'BF' => 'BFA',
'BG' => 'BGR',
'BA' => 'BIH',
'BB' => 'BRB',
'WF' => 'WLF',
'BL' => 'BLM',
...
ネストされた配列がある場合、この出力はより良く見えます...
これが役立つことを願っています...
あなたはこのようなことを試すことができます -
curl -s 'http://Twitter.com/users/jaypalsingh.json' |
awk -F=":" -v RS="," '$1~/"text"/ {print}'
入れ子になった構造を必要とせずに単純なJSONオブジェクトから値を抽出したいだけであれば、bashから離れずに正規表現を使用することが可能です。
これは、 JSON標準 に基づくbash正規表現を使用して定義した関数です。
function json_extract() {
local key=$1
local json=$2
local string_regex='"([^"\]|\\.)*"'
local number_regex='-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?'
local value_regex="${string_regex}|${number_regex}|true|false|null"
local pair_regex="\"${key}\"[[:space:]]*:[[:space:]]*(${value_regex})"
if [[ ${json} =~ ${pair_regex} ]]; then
echo $(sed 's/^"\|"$//g' <<< "${BASH_REMATCH[1]}")
else
return 1
fi
}
警告:オブジェクトと配列は値としてサポートされていませんが、標準で定義されている他のすべての値タイプはサポートされています。また、JSON文書内でキーの名前がまったく同じであれば、ペアは一致します。
OPの例を使うと:
$ json_extract text "$(curl 'http://Twitter.com/users/username.json')"
My status
$ json_extract friends_count "$(curl 'http://Twitter.com/users/username.json')"
245
これもまた別のbash
とpython
のハイブリッドな答えです。私はより複雑なJSON出力を処理したいのでこの答えを投稿しましたが、私のbashアプリケーションの複雑さを軽減しました。 bash
内の http://www.arcgis.com/sharing/rest/info?f=json から次のJSONオブジェクトをクラックオープンしたいです。
{
"owningSystemUrl": "http://www.arcgis.com",
"authInfo": {
"tokenServicesUrl": "https://www.arcgis.com/sharing/rest/generateToken",
"isTokenBasedSecurity": true
}
}
このアプローチはPython関数の複雑さを増しますが、bashの使い方はより単純になります。
function jsonGet {
python -c 'import json,sys
o=json.load(sys.stdin)
k="'$1'"
if k != "":
for a in k.split("."):
if isinstance(o, dict):
o=o[a] if a in o else ""
Elif isinstance(o, list):
if a == "length":
o=str(len(o))
Elif a == "join":
o=",".join(o)
else:
o=o[int(a)]
else:
o=""
if isinstance(o, str) or isinstance(o, unicode):
print o
else:
print json.dumps(o)
'
}
curl -s http://www.arcgis.com/sharing/rest/info?f=json | jsonGet
curl -s http://www.arcgis.com/sharing/rest/info?f=json | jsonGet authInfo
curl -s http://www.arcgis.com/sharing/rest/info?f=json | jsonGet authInfo.tokenServicesUrl
上記のスクリプトの出力は次のとおりです。
私は配列のサポートを追加したので、あなたは.length
を使うことができます、そしてもしソースが文字列配列なら、あなたは.join
を使うことができます:
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.length
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.0.resourceInfo.tileInfo.lods
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.0.resourceInfo.tileInfo.lods.length
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.0.resourceInfo.tileInfo.lods.23
どの出力:
これがawkでできる一つの方法です。
curl -sL 'http://Twitter.com/users/username.json' | awk -F"," -v k="text" '{
gsub(/{|}/,"")
for(i=1;i<=NF;i++){
if ( $i ~ k ){
print $i
}
}
}'
より複雑なJSONの構文解析のために私は(Stefan Goessnerによる)python jsonpathモジュールを使うことを勧めます
Sudo easy_install -U jsonpath
File.jsonの例( http://goessner.net/articles/JsonPath から) -
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
それをパースしなさい(価格<10ですべての本のタイトルを抽出する) -
$ cat file.json | python -c "import sys, json, jsonpath; print '\n'.join(jsonpath.jsonpath(json.load(sys.stdin), 'store.book[?(@.price < 10)].title'))"
出力します -
Sayings of the Century
Moby Dick
注:上記のコマンドラインにはエラーチェックは含まれていません。エラーチェックによる完全な解決策を得るには、小さなPythonスクリプトを作成し、そのコードをtry-exceptでラップする必要があります。
システムでpip
が利用可能な場合:
$ pip install json-query
使用例:
$ curl -s http://0/file.json | json-query
{
"key":"value"
}
$ curl -s http://0/file.json | json-query my.key
value
$ curl -s http://0/file.json | json-query my.keys.
key_1
key_2
key_3
$ curl -s http://0/file.json | json-query my.keys.2
value_2
非常にシンプルだが強力なJSON CLI処理ツールfx - https://github.com/antonmedv/fx
例
無名関数を使う:
$ echo '{"key": "value"}' | fx "x => x.key"
value
無名関数param => ...を渡さないと、コードは自動的に無名関数に変換されます。そして、このキーワードで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。新しい構文を学ぶ必要はありません。
UPDATE 2018-11-06
fx
はインタラクティブモードになりました(!)
JSON文字列からプロパティを取得するより簡単な方法があります。例としてpackage.json
ファイルを使用して、これを試してください:
#!/usr/bin/env bash
my_val="$(json=$(<package.json) node -pe "JSON.parse(process.env.json)['version']")"
これはprocess.env
を使用しています。これは、悪意のあるコンテンツが引用符をエスケープしてコードとして解析される危険性がなく、ファイルのコンテンツを文字列としてnode.jsに取り込むためです。
JSONの解析は、シェルスクリプトでは苦痛です。より適切な言語を使用して、シェルスクリプトの規則と一貫した方法でJSON属性を抽出するツールを作成します。新しいツールを使用して、差し迫ったシェルスクリプトの問題を解決し、将来の状況に備えてキットに追加できます。
たとえば、ツールjsonlookupを考えてみましょう。jsonlookup access token id
と言うと、属性内に定義された属性idが返されますtoken defined属性内access stdinから。これはおそらくJSONデータです。属性が存在しない場合、ツールは何も返しません(終了ステータス1)。解析が失敗した場合、終了ステータス2とstderrへのメッセージ。ルックアップが成功すると、ツールは属性の値を出力します。
JSON値を抽出するという正確な目的のためにUNIXツールを作成したら、シェルスクリプトで簡単に使用できます。
access_token=$(curl <some horrible crap> | jsonlookup access token id)
どの言語でもjsonlookupの実装に対応できます。これはかなり簡潔なpythonバージョンです:
#!/usr/bin/python
import sys
import json
try: rep = json.loads(sys.stdin.read())
except:
sys.stderr.write(sys.argv[0] + ": unable to parse JSON from stdin\n")
sys.exit(2)
for key in sys.argv[1:]:
if key not in rep:
sys.exit(1)
rep = rep[key]
print rep
Pythonを使ったツーライナー。単一の.shファイルを作成していて、別の.pyファイルに依存したくない場合は、特に有効です。また、パイプ|
の使用法も活用しています。 echo "{\"field\": \"value\"}"
は、標準出力にJSONを出力するものに置き換えることができます。
echo "{\"field\": \"value\"}" | python -c 'import sys, json
print(json.load(sys.stdin)["field"])'
これは、 python の適切な使用例です。
curl 'http://Twitter.com/users/username.json' | py 'json.load(sys.stdin)["name"]'
私はこれを使ってffprobe jsonの出力からビデオのデュレーションを抽出しました:
MOVIE_INFO=`ffprobe "path/to/movie.mp4" -show_streams -show_format -print_format json -v quiet`
MOVIE_SECONDS=`echo "$MOVIE_INFO"|grep -w \"duration\" |tail -1 | cut -d\" -f4 |cut -d \. -f 1`
任意のJSONから値を抽出するために使用できます。
value=`echo "$jsondata"|grep -w \"key_name\" |tail -1 | cut -d\" -f4
これは良い参考です 。この場合:
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++) { where = match(a[i], /\"text\"/); if(where) {print a[i]} } }'
bashJson を使えます
Pythonのjsonモジュールのラッパーで、複雑なjsonデータを処理できます。
ファイルtest.json
からのこのjsonデータの例を考えてみましょう。
[ { "名前": "テストツール"、 "作者": "hack4mer"、 "supported_os":{ ] osx ":{[。____。" "foo": "bar"、 "min_version":10.12、 "testing_on":[10.1,10.13] ]、[。 "ubuntu":{ "min_version":14.04、 "testing_on":16.04 } } }
以下のコマンドは、このサンプルjsonファイルからデータを読み取ります
./bashjson.sh test.json name
印刷物:テストツール
./bashjson.sh test.json supported_os osx foo
プリント:バー
./bashjson.sh test.json supported_os osx tested_on
プリント:[10.1、10.13]
次のように、これを行って、特定の値に対するJSON応答を「解析」します。
curl $url | grep $var | awk '{print $2}' | sed s/\"//g
明らかに、ここでの$ urlはTwitterのURLであり、$ varはそのvarに対する応答を得るための "テキスト"です。
本当に、私がOPで行っているのは、彼が求めている特定の変数を持つ行に対するgrepだけです。 Awkはその行の2番目の項目をつかみ、sedを使って引用符を取り除きます。
私よりも賢い人は、おそらく全体をawkやgrepで考えることができるでしょう。
今、あなたはちょうどsedでそれをすべて行うことができます:
curl $url | sed '/text/!d' | sed s/\"text\"://g | sed s/\"//g | sed s/\ //g
つまり、awkもgrepもありません...私は以前、なぜそれを考えなかったのかわかりません。うーん...
私はBASHで短いものを必要としていました、そしてpython 2.7と3の両方のためにVanilla Linux LSBとMac OSを越えた依存性なしで走り、そしてエラーを処理するでしょう。 Pythonの例外を発生させることなく、JSONの解析エラーとプロパティの欠落エラーを報告します。
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-file 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
}
Niet は、シェル/ bash CLIで直接jsonファイルまたはyamlファイルからデータを抽出するのに役立つツールです。
$ pip install niet
次の内容を持つproject.jsonという名前のjsonファイルを考えます。
{
project: {
meta: {
name: project-sample
}
}
あなたはこのようにnietを使うことができます:
$ PROJECT_NAME=$(niet project.json project.meta.name)
$ echo ${PROJECT_NAME}
project-sample