我试图解析从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=文本表示)?
你可以使用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]
对于更复杂的JSON解析,我建议使用Python jsonpath模块(Stefan Goessner) -
Install it -
sudo easy_install -U jsonpath
Use it -
Example file.json (from 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
}
}
}
Parse it (extract all book titles with price < 10) -
cat file.json | python -c "import sys, json, jsonpath; print '\n'.join(jsonpath.jsonpath(json.load(sys.stdin), 'store.book[?(@.price < 10)].title'))"
Will output -
Sayings of the Century
Moby Dick
Note: The above command line does not include error checking. For a full solution with error checking, you should create a small Python script, and wrap the code with try-except.
既然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就是其中之一。这是跨平台版本PowerShell的GitHub页面
这里我不能用任何答案。jq、shell数组、声明、grep -P、后视、前视、Python、Perl、Ruby甚至Bash都不可用。
剩下的答案都不太管用。JavaScript听起来很熟悉,但罐头上写的是Nescaffe——所以也不行:)即使有,对于我的简单需求——它们也会过度消耗和缓慢。
然而,对我来说,从我的调制解调器的JSON格式的回复中获得许多变量是极其重要的。我在Bourne shell (sh)做它与一个非常修剪下来的BusyBox在我的路由器!单独使用AWK没有任何问题:只需设置分隔符并读取数据。对于单个变量,这就是全部!
awk 'BEGIN { FS="\""; RS="," }; { if ($2 == "login") {print $4} }' test.json
还记得我没有数组吗?我必须在AWK解析数据中分配给我在shell脚本中需要的11个变量。我所到之处,都有人说这是不可能完成的任务。这也没有问题。
我的解决办法很简单。这段代码将:
parse .json file from the question (actually, I have borrowed a working data sample from the most upvoted answer) and picked out the quoted data, plus
create shell variables from within the awk assigning free named shell variable names.
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秒vs. 0.02秒。
更新(2020)
我使用外部工具(例如Python)时遇到的最大问题是,你必须处理包管理器和安装它们的依赖关系。
然而,现在我们有了jq作为一个独立的静态工具,很容易通过GitHub发布和Webi (webinstall.dev/jq)跨平台安装,我建议:
Mac、Linux:
curl -sS https://webi.sh/jq | bash
Windows 10:
curl.exe -A MS https://webi.ms/jq | powershell
小抄:https://webinstall.dev/jq
原(2011)
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
如果你正在寻找一个本地Mac解决方案来解析JSON(没有外部库等…),那么这是为你。
此信息来自https://www.macblog.org/parse-json-command-line-mac/
简而言之,自从Mac OS Yosemite有一个运行苹果脚本的工具叫做osascript,但是如果你传递-l 'Javascript'标志,你可以运行Javascript !这就是所谓的使用JXA (JavaScript for Automation)。
下面是为我自己的项目读取JSON文件的示例。
DCMTK_JSON=$(curl -s https://formulae.brew.sh/api/bottle/dcmtk.json) # -s for silent mode
read -r -d '' JXA <<EOF
function run() {
var json = JSON.parse(\`$DCMTK_JSON\`);
return json.bottles.$2.url;
}
EOF
DOWNLOAD_URL=$( osascript -l 'JavaScript' <<< "${JXA}" )
echo "DOWNLOAD_URL=${DOWNLOAD_URL}"
这里所发生的是我们将函数的输出存储到变量JXA中。然后我们可以使用JSON.parse()简单地运行javascript来解析JSON内容。然后简单地将包含脚本的JXA变量传递给osascript工具,以便它可以运行javascript。在我的例子中,如果测试的话,$2指的是arm64_monterey。javascript立即运行的原因是特殊的run()函数,JXA将查找该函数并在完成时返回其输出。
注意EOF(文件的结尾)用于处理多行文本输入,并且结束的EOF前面不能有任何空格。
您可以通过简单地打开终端并键入下面的命令来测试这是否适合您
osascript -l 'JavaScript' -e 'var app = Application.currentApplication(); app.includeStandardAdditions = true; app.displayDialog("Hello from JavaScript!");
这应该会弹出一个从javascript说hello的窗口