使用Unix工具解析JSON

时间:2009-12-23 21:46:59

标签: json bash parsing

我正在尝试解析从curl请求返回的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表示)?

40 个答案:

答案 0 :(得分:845)

有许多专门用于从命令行操作JSON的工具,比使用Awk更容易,更可靠,例如jq

curl -s 'https://api.github.com/users/lambda' | jq -r '.name'

您也可以使用可能已经安装在系统上的工具(例如使用json module的Python)执行此操作,从而避免任何额外的依赖关系,同时仍然可以使用正确的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解释器,它不像Python解释器那么常见,所以上述答案可能更可取:

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'

答案 1 :(得分:255)

要快速提取特定键的值,我个人喜欢使用“grep -o”,它只返回正则表达式的匹配。例如,要从推文中获取“文本”字段,请执行以下操作:

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

这个正则表达式比你想象的更强大;例如,它可以很好地处理嵌入了逗号并在其中包含转义引号的字符串。我认为通过更多的工作,你可以制作一个实际上可以保证提取值,如果它是原子的。 (如果它有嵌套,那么正则表达式当然不能这样做。)

要进一步清理(虽然保持字符串的原始转义),您可以使用类似:| perl -pe 's/"text"://; s/^"//; s/",$//'的内容。 (我为this analysis做了这个。)

对于那些坚持要求你使用真正的JSON解析器的仇恨者 - 是的,这对正确性至关重要,但是

  1. 要做一个非常快速的分析,比如计算值以检查数据清理错误或获得对数据的一般感觉,在命令行上敲打一些东西会更快。打开编辑器编写脚本会分散注意力。
  2. grep -o比Python标准json库快几个数量级,至少在为推文执行此操作时(每个约2 KB)。我不确定这是不是因为json很慢(我应该在某个时候与yajl比较);但原则上,正则表达式应该更快,因为它是有限状态并且更加可优化,而不是必须支持递归的解析器,并且在这种情况下,为您不关心的结构花费大量CPU构建树。 (如果有人写了一个有限状态传感器,它做了适当的(深度限制的)JSON解析,那就太棒了!同时我们有“grep -o”。)
  3. 要编写可维护的代码,我总是使用真正的解析库。我没有尝试过jsawk,但如果效果很好,那就会解决第一点问题。

    最后一个更糟糕的解决方案:我编写了一个使用Python json的脚本并将所需的键提取到以制表符分隔的列中;然后我通过awk周围的包装器管道,允许对列进行命名访问。 In here: the json2tsv and tsvawk scripts。因此,对于这个例子,它将是:

    json2tsv id text < tweets.json | tsvawk '{print "tweet " $id " is: " $text}'
    

    这种方法没有解决#2问题,比单个Python脚本效率更低,而且有点脆弱:它强制对字符串值中的换行符和制表符进行规范化,以便与awk的字段/记录分隔视图一起使用世界。但它确实让你留在命令行,其正确性超过grep -o

答案 2 :(得分:158)

基于这里的一些建议(特别是在评论中)建议使用Python,我很失望没有找到一个例子。

所以,这是一个单行程序来从一些JSON数据中获取单个值。它假设您正在(从某处)管道数据,因此在脚本环境中应该是有用的。

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

答案 3 :(得分:124)

继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

答案 4 :(得分:119)

您可以download jq binary for your platform并运行(chmod +x jq):

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

它从json对象中提取"name"属性。

jq homepage表示它与JSON数据的sed类似。

答案 5 :(得分:93)

使用Python's JSON support代替使用awk!

这样的事情:

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

答案 6 :(得分:88)

使用Node.js

如果系统安装了,则可以使用-p打印和-e evaulate脚本标记和JSON.parse来提取所需的任何值。< / p>

使用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的网址:

$ node -pe 'JSON.parse(process.argv[1]).name' "$(curl -s https://api.github.com/users/trevorsenior)"
Trevor Senior

答案 7 :(得分:52)

你已经问过如何用脚射击自己,我在这里提供弹药:

curl -s 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^text/ {print $2}'

您可以使用tr -d '{}'代替sed。但是将它们完全排除在外似乎也具有预期的效果。

如果要剥离外部引号,请通过sed 's/\(^"\|"$\)//g'

管道上述结果

我认为其他人已经发出足够的警报。我会站着用手机打电话给救护车。准备好时开火。

答案 8 :(得分:40)

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

答案 9 :(得分:25)

TickTick是用bash编写的JSON解析器(&lt; 250行代码)

以下是作者的文章Imagine a world where Bash supports JSON中的snippit:

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

答案 10 :(得分:19)

使用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;'

的nJoy!

答案 11 :(得分:18)

Native 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":"john@doe.com"}' username
parse_json '{"username":"john doe","email":"john@doe.com"}' email

--- outputs ---

john, doe
johh@doe.com

答案 12 :(得分:12)

使用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]);"

答案 13 :(得分:10)

不幸的是,使用grep的最高投票回答会返回在我的方案中无效的完整匹配,但如果您知道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

答案 14 :(得分:6)

现在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

最后,还有'ConvertTo-Json',它可以轻松地将自定义对象转换为JSON。这是一个例子:

(New-Object PsObject -Property @{ Name = "Tester"; SomeList = @('one','two','three')}) | ConvertTo-Json

哪个会生成这样的好JSON:

{
"Name":  "Tester",
"SomeList":  [
                 "one",
                 "two",
                 "three"
             ]

}

不可否认,在Unix上使用Windows shell有点亵渎神灵,但Powershell在某些方面非常擅长,解析JSON和XML是其中的几个。这是跨平台版本https://github.com/PowerShell/PowerShell

的GitHub页面

答案 15 :(得分:5)

您可以使用jshon

curl 'http://twitter.com/users/username.json' | jshon -e text

答案 16 :(得分:5)

我在这里无法使用任何答案。没有可用的jq,没有shell数组,没有声明,没有grep -P,没有后向和超前,没有Python,没有Perl,没有Ruby,甚至-甚至Bash ...其余答案根本无法正常工作。 JavaScript听起来很熟悉,但是锡说Nescaffe-所以也不行:)即使可用,就我的简单需求而言-它们也会过大且缓慢。

但是,对我来说,从调制解调器的json格式答复中获取许多变量对我来说非常重要。我在路由器上用非常精简的BusyBox进行了处理!单独使用awk没问题:只需设置分隔符并读取数据。对于一个变量,仅此而已!

awk 'BEGIN { FS="\""; RS="," }; { if ($2 == "login") {print $4} }' test.json

还记得我没有数组吗?我必须在awk中将解析的数据分配给shell脚本中需要的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个变量:0.51与0.02秒。

答案 17 :(得分:5)

如果有人只想从简单的JSON对象中提取值而不需要嵌套结构,则可以使用正则表达式而不需要保留bash。

这是我使用基于JSON standard的bash正则表达式定义的函数:

.flatMap

警告:不支持对象和数组作为值,但支持标准中定义的所有其他值类型。此外,只要它具有完全相同的密钥名称,无论JSON文档有多深,都会匹配一对。

使用OP的例子:

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
}

答案 18 :(得分:5)

也有xml文件的人可能想查看我的Xidel。它是一个cli,无依赖的JSONiq处理器。 (即它也支持XQuery for xml或json处理)

问题中的例子是:

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

或者使用我自己的非标准扩展语法:

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

答案 19 :(得分:4)

对于更复杂的JSON解析,我建议使用python jsonpath模块(由Stefan Goessner提供) -

  1. 安装 -
  2. sudo easy_install -U jsonpath

    1. 使用它 -
    2. 示例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包装代码。

答案 20 :(得分:4)

这是使用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
        }
    }
}'

答案 21 :(得分:4)

如果你有 php

php -r 'var_export(json_decode(`curl http://twitter.com/users/username.json`, 1));'

例如:
我们有资源为json提供国家iso代码:http://country.io/iso3.json,我们可以很容易地在curl的shell中看到它:

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

如果你有嵌套数组,这个输出看起来会更好......

希望这会有所帮助......

答案 22 :(得分:4)

这是另一个bash&amp; 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

哪个输出:

  • 1
  • [{&#34; scale&#34;:591657527.591555,&#34; resolution&#34;:156543.03392800014,&#34; level&#34;:0},{&#34; scale&#34;:295828763.795777 ,&#34;分辨率&#34;:78271.51696399994,&#34;等级&#34;:1},{&#34;比例&#34;:147914381.897889,&#34;分辨率&#34;:39135.75848200009,&#34 ;等级&#34;:2},{&#34;比例&#34;:73957190.948944,&#34;决议&#34;:19567.87924099992,&#34;等级&#34;:3},{&#34;比例& #34;:36978595.474472,&#34;分辨率&#34;:9783.93962049996,&#34;等级&#34;:4},{&#34;比例&#34;:18489297.737236,&#34;分辨率&#34;: 4891.96981024998,&#34; level&#34;:5},{&#34; scale&#34;:9244648.868618,&#34; resolution&#34;:2445.98490512499,&#34; level&#34;:6},{ &#34; scale&#34;:4622324.434309,&#34; resolution&#34;:1222.992452562495,&#34; level&#34;:7},{&#34; scale&#34;:2311162.217155,&#34;分辨率&#34;:611.4962262813797,&#34;等级&#34;:8},{&#34;比例&#34;:1155581.108577,&#34;分辨率&#34;:305.74811314055756,&#34;等级&#34; :9},{&#34; scale&#34;:577790.55 4289,&#34;分辨率&#34;:152.87405657041106,&#34;等级&#34;:10},{&#34;比例&#34;:288895.277144,&#34;分辨率&#34;:76.43702828507324,&# 34; level&#34;:11},{&#34; scale&#34;:144447.638572,&#34; resolution&#34;:38.21851414253662,&#34; level&#34;:12},{&#34; scale&#34;:72223.819286,&#34; resolution&#34;:19.10925707126831,&#34; level&#34;:13},{&#34; scale&#34;:36111.909643,&#34; resolution&#34; :9.554628535634155,&#34; level&#34;:14},{&#34; scale&#34;:18055.954822,&#34; resolution&#34;:4.77731426794937,&#34; level&#34;:15}, {&#34; scale&#34;:9027.977411,&#34; resolution&#34;:2.388657133974685,&#34; level&#34;:16},{&#34; scale&#34;:4513.988705,&#34 ;分辨率&#34;:1.1943285668550503,&#34;等级&#34;:17},{&#34;比例&#34;:2256.994353,&#34;分辨率&#34;:0.5971642835598172,&#34;等级&#34 ;:18},{&#34; scale&#34;:1128.497176,&#34; resolution&#34;:0.29858214164761665,&#34; level&#34;:19},{&#34; scale&#34;: 564.248588,&#34; resolution&#34;:0.14929107082380833,& #34;等级&#34;:20},{&#34;比例&#34;:282.124294,&#34;分辨率&#34;:0.07464553541190416,&#34;等级&#34;:21},{&#34 ; scale&#34;:141.062147,&#34; resolution&#34;:0.03732276770595208,&#34; level&#34;:22},{&#34; scale&#34;:70.5310735,&#34; resolution&#34 ;:0.01866138385297604,&#34;等级&#34;:23}]
  • 24
  • {&#34; scale&#34;:70.5310735,&#34; resolution&#34;:0.01866138385297604,&#34; level&#34;:23}

答案 23 :(得分:4)

你可以尝试这样的事情 -

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

答案 24 :(得分:3)

这是pythonpy的一个很好的用例:

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

答案 25 :(得分:3)

现有答案中没有涉及的一个有趣的工具是使用 gron written in Go,它的标语是 Make JSON grepable! 这正是它的作用是什么。

因此基本上 gron 将您的 JSON 分解为离散的分配,请参阅它的绝对“路径”。与 jq 等其他工具相比,它的主要优势是允许在不知道要搜索的记录是如何嵌套的情况下搜索值,而不会破坏原始 JSON 结构

例如,我想从以下链接中搜索 'twitter_username' 字段,我只是这样做

% gron 'https://api.github.com/users/lambda' | fgrep 'twitter_username'
json.twitter_username = "unlambda";
% gron 'https://api.github.com/users/lambda' | fgrep 'twitter_username' | gron -u
{
  "twitter_username": "unlambda"
}

就这么简单。请注意 gron -u(ungron 的缩写)如何从搜索路径重建 JSON。 fgrep 的需要只是将您的搜索过滤到所需的路径,而不是让搜索表达式被评估为正则表达式,而是作为固定字符串(本质上是 grep -F

搜索字符串以查看记录在嵌套结构中的位置的另一个示例

% echo '{"foo":{"bar":{"zoo":{"moo":"fine"}}}}' | gron | fgrep "fine"
json.foo.bar.zoo.moo = "fine";

它还支持流 JSON 及其 -s 命令行标志,您可以在其中连续 gron 输入流以获取匹配记录。此外,gron 的运行时依赖项为零。您可以为 Linux、Mac、Windows 或 FreeBSD download a binary 并运行它。

更多使用示例和行程可以在 Github 官方页面找到 - Advanced Usage

至于为什么您可以使用 gron 而不是其他 JSON 解析工具,请参阅项目页面的作者注释。

为什么我不应该只使用 jq?

<块引用>

jq 很棒,而且比 gron 强大得多,但随着这种力量的增加,复杂性也随之而来。 gron 旨在让您更轻松地使用您已知的工具,例如 grep 和 sed。

答案 26 :(得分:3)

还有一个非常简单但功能强大的 JSON CLI 处理工具 fx - https://github.com/antonmedv/fx

Example of JSON formatting in Bash terminal

实施例

使用匿名函数:

$ echo '{"key": "value"}' | fx "x => x.key"
value

如果您没有通过匿名函数param =&gt; ...,代码将自动转换为匿名函数。您可以通过以下关键字访问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

您可以使用spread运算符更新现有的JSON:

$ echo '{"count": 0}' | fx "{...this, count: 1}"
{"count": 1}

只是简单的JavaScript 。不需要学习新语法。

更新2018-11-06

fx现在具有互动模式(

https://github.com/antonmedv/fx

答案 27 :(得分:3)

有一种更简单的方法从json字符串获取属性。以package.json文件为例,试试这个:

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

我们正在使用process.env因为这会将文件的内容作为字符串传递给node.js,而不会有任何恶意内容逃脱引用并被解析为代码的风险。

答案 28 :(得分:3)

解析JSON在shell脚本中很痛苦。使用更合适的语言,创建一个以与shell脚本约定一致的方式提取JSON属性的工具。您可以使用新工具解决即时shell脚本问题,然后将其添加到您的工具包中以备将来使用。

例如,考虑一个工具 jsonlookup ,如果我说jsonlookup access token id,它将返回属性标记中定义的 id 属性在stdin的属性 access 中定义,可能是JSON数据。如果该属性不存在,则该工具不返回任何内容(退出状态1)。如果解析失败,请退出状态2并向stderr发送消息。如果查找成功,则工具将打印属性的值。

创建一个用于提取JSON值的精确目的的unix工具,您可以在shell脚本中轻松使用它:

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

答案 29 :(得分:3)

如果系统上有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

答案 30 :(得分:3)

使用python的双线程。如果您正在编写单个.sh文件并且不想依赖另一个.py文件,那么它的效果特别好。它还利用了管道|的使用。任何将json打印到stdout的东西都可以替换echo "{\"field\": \"value\"}"

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

答案 31 :(得分:2)

我用它来从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

答案 32 :(得分:2)

Here is a good reference。在这种情况下:

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

答案 33 :(得分:2)

以下是使用POSIX shell(带有local)和egrep的shell呆子的答案:JSON.sh,4.7 KB。

这个东西有很多测试用例,所以应该是正确的。它也是可管道的。在软件包管理器中用于bash bpkg。

答案 34 :(得分:1)

Niet是一个工具,可以帮助您直接在shell / 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

答案 35 :(得分:1)

您可以使用bashJson

它是Python的json模块的包装,并且可以处理复杂的json数据。

让我们考虑来自文件test.json的这个出色的json数据

{
    "name":"Test tool",
    "author":"hack4mer",
    "supported_os":{
        "osx":{
            "foo":"bar",
            "min_version" : 10.12,
            "tested_on" : [10.1,10.13]
        },
        "ubuntu":{
            "min_version":14.04,
            "tested_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]

答案 36 :(得分:1)

我已完成此操作,“解析”特定值的json响应,如下所示:

curl $url | grep $var | awk '{print $2}' | sed s/\"//g 

显然,这里的$ url将是twitter url,而$ var将是“text”以获取该var的响应。

真的,我认为我做OP的唯一一件事就是用他想要的特定变量的线条grep。 Awk抓住了第二个项目,并使用sed我删除了引号。

比我聪明的人可能会用awk或grep做整个想法。

现在,你可以用sed来完成所有这些:

curl $url | sed '/text/!d' | sed s/\"text\"://g | sed s/\"//g | sed s/\ //g
因此,没有awk,没有grep ......我不知道为什么我之前没有想到这一点。嗯...

答案 37 :(得分:1)

我在BASH中需要一些简短的东西,并且可以在没有依赖于python 2.7&3的普通Linux LSB和Mac OS的情况下运行,并且可以处理错误,例如会报告json解析错误和缺少的属性错误,而不会产生python异常:

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
}

答案 38 :(得分:1)

这是适用于Node.js的环境的简单方法:

curl -L https://github.com/trentm/json/raw/master/lib/json.js > json
chmod +x json
echo '{"hello":{"hi":"there"}}' | ./json "hello.hi"

答案 39 :(得分:-1)

yum install php-cli 之后使用 php:

php -r " foreach(json_decode(file_get_contents('http://a.com/a.json'), true) as \$key => \$value) echo \$key.'='.\$value.\"\n\" ; "