web-dev-qa-db-ja.com

UnixツールでJSONを解析する

私はカールリクエストから返された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で表される)を印刷するにはどうすればいいですか?

697
auser

コマンドラインから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'
831
Brian Campbell

特定のキーの値を素早く抽出するために、私は個人的に "grep -o"を使うのが好きです。これは正規表現のマッチだけを返します。たとえば、ツイートから「テキスト」フィールドを取得するには、次のようにします。

grep -Po '"text":.*?[^\\]",' tweets.json

この正規表現はあなたが思う以上に堅牢です。例えば、それは、埋め込まれたコンマとエスケープされた引用符を含む文字列をうまく扱います。アトミックであれば、もう少し作業をして、実際に値を引き出すことが保証されているものを作成できると思います。 (入れ子になっている場合、正規表現ではもちろんできません。)

(文字列の元のエスケープを維持しながら)さらにクリーンにするには、| Perl -pe 's/"text"://; s/^"//; s/",$//'のようなものを使用できます。 (私はこれを この分析のために に行った。)

あなたが本当のJSONパーサを使うべきだと主張するすべての憎しみに - はい、それは正確さのために不可欠ですが、

  1. 値を数えてデータクリーニングのバグをチェックしたり、データの一般的な感覚を得たりするなど、本当に迅速な分析を実行するには、コマンドラインで何かを実行するほうが速くなります。スクリプトを書くためにエディタを開くのは面倒です。
  2. 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よりも正確で、あなたがコマンドラインにとどまることを可能にします。

255
Brendan OConnor

ここでのいくつかの推奨(特にコメント内)がPythonの使用を示唆していることに基づいて、私は例を見つけないことに失望しました。

それで、ここにいくつかのJSONデータから単一の値を得るための一つの裏書があります。それはあなたが(どこかから)データをパイプインしていると仮定しているので、スクリプトの文脈では役に立つはずです。

echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["hostname"]'
156
paulkmoore

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
123
jnrg

あなたは あなたのプラットフォーム用のjqバイナリをダウンロードすることができます そして(chmod +x jq)を実行することができます:

$ curl 'https://Twitter.com/users/username.json' | ./jq -r '.name'

Jsonオブジェクトから"name"属性を抽出します。

jqホームページ JSONデータのsedのようなものです。

118
jfs

Awkの代わりに PythonのJSONサポート を使用してください。

このようなもの:

curl -s http://Twitter.com/users/username.json | \
    python -c "import json,sys;obj=json.load(sys.stdin);print obj['name'];"
92
martinr

Node.jsを使用する

システムに node がインストールされている場合は、-p printおよび-eJSON.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
87
JayQuerie.com

あなたは自分の足を撃つ方法を頼んだ、そして私は弾薬を提供するためにここにいる:

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'に渡してください。

私は他人が十分な警告を鳴らしたと思います。私は救急車を呼ぶために携帯電話で待機します。準備ができたら発砲します。

52

PythonでBashを使う

.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"
}
40
Joe Heyming

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
24
CoolAJ86

PHP CLIによるJSONの解析

議論の余地はありませんが、優先順位が支配しているので、この質問は私たちの信頼でき、忠実なPHPについての言及がなければ不完全なままです。

同じサンプルJSONを使用しますが、それを変数に割り当てて、不明瞭さを軽減します。

$ export JSON='{"hostname":"test","domainname":"example.com"}'

今度はPHPのために、 file_get_contentsphp:// 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ジョイ!

19
nickl-

ネイティブ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]
18
maikel

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]);"
12
boecko

残念ながら、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
9

私はここで答えのどれも使うことができません。利用可能な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秒。

5
Pila

Xmlファイルも持っている人は、私の Xidel を見たいと思うかもしれません。これはcli、依存関係のない JSONiq プロセッサです。 (つまり、xmlまたはjson処理のためのXQueryもサポートします)

質問の例は次のようになります。

 xidel -e 'json("http://Twitter.com/users/username.json")("name")'

あるいは私自身の、標準ではない拡張構文を使います。

 xidel -e 'json("http://Twitter.com/users/username.json").name'
5
BeniBela

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

5
user2233949

jshon を使用できます。

curl 'http://Twitter.com/users/username.json' | jshon -e text
5
kev

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',
  ...

ネストされた配列がある場合、この出力はより良く見えます...

これが役立つことを願っています...

4
Vladimir Kovpak

あなたはこのようなことを試すことができます -

curl -s 'http://Twitter.com/users/jaypalsingh.json' | 
awk -F=":" -v RS="," '$1~/"text"/ {print}'
4
jaypal singh

入れ子になった構造を必要とせずに単純な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
4
Helder Pereira

これもまた別のbashpythonのハイブリッドな答えです。私はより複雑な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

どの出力:

  • 1
  • [{"スケール":591657527.591555、 "解像度":156543.03392800014、 "レベル":0}、{"スケール":295828763.795777、 "解像度":78271.51696399994、 "レベル":1}、{"スケール":147914381.897889、 "解像度":39135.75848200009、"レベル ":2}、{"スケール ":73957190.948944、"解像度 ":19567.87924099992、"レベル ":3}、{"スケール ":36978595.474472、"解像度 ":9783.93962049996、"レベル ":4} 、{"scale":18489297.737236、 "resolution":4891.96981024998、 "level":5}、{"scale":9244648.868618、 "resolution":2445.98490512499、 "level":6}、{"scale":4622324.434309、 "resolution ":1222.992452562495、"レベル ":7}、{"スケール ":2311162.217155、"解像度 ":611.4962262813797、"レベル ":8}、{"スケール ":1155581.108577、"解像度 ":305.74811314055756、"レベル ":9} 、{"scale":577790.554289、 "resolution":152.87405657041106、 "level":10}、{"scale":288895.277144、 "resolution":76.43702828507324、 "level":11}、{"scale":144447.638572、 "resolution" ":38.21851414253662、"レベル ":12}、{"スケール ":72223.819286、"解像度 ":19.1092570712683 1、 "レベル":13}、{"スケール":36111.909643、 "解像度":9.554628535634155、 "レベル":14}、{"スケール":18055.954822、 "解像度":4.77731426794937、 "レベル":15}、{ "スケール":9027.977411、 "解像度":2.388657133974685、 "レベル":16}、{"スケール":4513.988705、 "解像度":1.1943285668550503、 "レベル":17}、{"スケール":2256.994353、 "解像度": 0.5971642835598172、 "レベル":18}、{"スケール":1128.497176、 "解像度":0.29858214164761665、 "レベル":19}、{"スケール":564.248588、 "解像度":0.14929107082380833、 "レベル":20}、{ "スケール":282.124294、 "解像度":0.07464553541190416、 "レベル":21}、{"スケール":141.062147、 "解像度":0.03732276770595208、 "レベル":22}、{"スケール":70.5310735、 "解像度": 0.01866138385297604、 "レベル":23}]
  • 24
  • {「スケール」:70.5310735、「解像度」:0.01866138385297604、「レベル」:23}
4
Stephen Quan

これが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
        }
    }
}'
4
ghostdog74

より複雑なJSONの構文解析のために私は(Stefan Goessnerによる)python jsonpathモ​​ジュールを使うことを勧めます

  1. それをインストール -

Sudo easy_install -U jsonpath

  1. これを使って -

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でラップする必要があります。

4
shlomosh

システムで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
3
Alexey Dubkov

非常にシンプルだが強力なJSON CLI処理ツールfx - https://github.com/antonmedv/fx

Example of JSON formatting in Bash terminal

無名関数を使う:

$ 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はインタラクティブモードになりました(

https://github.com/antonmedv/fx

3
Anton Medvedev

JSON文字列からプロパティを取得するより簡単な方法があります。例としてpackage.jsonファイルを使用して、これを試してください:

#!/usr/bin/env bash
my_val="$(json=$(<package.json) node -pe "JSON.parse(process.env.json)['version']")"

これはprocess.envを使用しています。これは、悪意のあるコンテンツが引用符をエスケープしてコードとして解析される危険性がなく、ファイルのコンテンツを文字列としてnode.jsに取り込むためです。

3
Alexander Mills

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
3
mcnabicus

Pythonを使ったツーライナー。単一の.shファイルを作成していて、別の.pyファイルに依存したくない場合は、特に有効です。また、パイプ|の使用法も活用しています。 echo "{\"field\": \"value\"}"は、標準出力にJSONを出力するものに置き換えることができます。

echo "{\"field\": \"value\"}" | python -c 'import sys, json
print(json.load(sys.stdin)["field"])'
3
Adam Kurkiewicz

これは、 python の適切な使用例です。

curl 'http://Twitter.com/users/username.json' | py 'json.load(sys.stdin)["name"]'
3
RussellStewart

私はこれを使って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
2
Ehsan Chavoshi

これは良い参考です 。この場合:

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]} }  }'
2
Max Barrass

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]

1
hack4mer

次のように、これを行って、特定の値に対する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もありません...私は以前、なぜそれを考えなかったのかわかりません。うーん...

1
tonybaldwin

私は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
}
1
Mike

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
1
Herve