下面是curl命令的输出(有关分支的文件信息),需要脚本或命令来打印文件名、文件类型和大小。
我尝试过jq
但能够获取单个值(jq '.values[].size'
)
{
"path": {
"components": [],
"name": "",
"toString": ""
},
"revision": "master",
"children": {
"size": 5,
"limit": 500,
"isLastPage": true,
"values": [
{
"path": {
"components": [
".gitignore"
],
"parent": "",
"name": ".gitignore",
"extension": "gitignore",
"toString": ".gitignore"
},
"contentId": "c9e472ef4e603480cdd85012b01bd5f4eddc86c6",
"type": "FILE",
"size": 224
},
{
"path": {
"components": [
"Jenkinsfile"
],
"parent": "",
"name": "Jenkinsfile",
"toString": "Jenkinsfile"
},
"contentId": "e878a88eed6b19b2eb0852c39bfd290151b865a4",
"type": "FILE",
"size": 1396
},
{
"path": {
"components": [
"README.md"
],
"parent": "",
"name": "README.md",
"extension": "md",
"toString": "README.md"
},
"contentId": "05782ad495bfe11e00a77c30ea3ce17c7fa39606",
"type": "FILE",
"size": 237
},
{
"path": {
"components": [
"pom.xml"
],
"parent": "",
"name": "pom.xml",
"extension": "xml",
"toString": "pom.xml"
},
"contentId": "9cd4887f8fc8c2ecc69ca08508b0f5d7b019dafd",
"type": "FILE",
"size": 2548
},
{
"path": {
"components": [
"src"
],
"parent": "",
"name": "src",
"toString": "src"
},
"node": "395c71003030308d1e4148b7786e9f331c269bdf",
"type": "DIRECTORY"
}
],
"start": 0
}
}
预期输出应如下所示
.gitignore FILE 224
Jenkinsfile FILE 1396
答案1
对于问题中提供的用例,@JigglyNaga 的答案可能比这更好,但对于一些更复杂的任务,您还可以使用以下方式循环遍历列表项keys
:
从file
:
for k in $(jq '.children.values | keys | .[]' file); do
...
done
或来自字符串:
for k in $(jq '.children.values | keys | .[]' <<< "$MYJSONSTRING"); do
...
done
例如,您可能会使用:
for k in $(jq '.children.values | keys | .[]' file); do
value=$(jq -r ".children.values[$k]" file);
name=$(jq -r '.path.name' <<< "$value");
type=$(jq -r '.type' <<< "$value");
size=$(jq -r '.size' <<< "$value");
printf '%s\t%s\t%s\n' "$name" "$type" "$size";
done | column -t -s$'\t'
如果值没有换行符,则可以jq
在循环内通过一次调用来完成,这会使其速度更快:
for k in $(jq '.children.values | keys | .[]' file); do
IFS=$'\n' read -r -d '' name type size \
<<< "$(jq -r ".children.values[$k] | .path.name,.type,.size" file)"
printf '%s\t%s\t%s\n' "$name" "$type" "$size";
done | column -t -s$'\t'
答案2
提取成员
jq -c '.children.values[]|[.path.components[0],.type,.size]'
.children.values[]
输出数组的每个成员.values
。|
将先前的结果通过下一个过滤器进行管道传输,就像外壳管道一样[
...,
...,
...]
使里面的所有术语出现在一个数组中- 该
-c
选项产生“紧凑”格式,即。每行一个对象
结果:
[".gitignore","FILE",224]
["Jenkinsfile","FILE",1396]
["README.md","FILE",237]
...
格式化结果
如果您想输出整齐对齐的表格,那么其他工具可以更好地处理这项任务,例如column
或者paste
。
jq -c '.children.values[]|[.path.components[0],.type,.size]' | column -t -s'[],"'
-t
告诉column
根据输入猜测列数-s...
指定分隔符
结果:
.gitignore FILE 224
Jenkinsfile FILE 1396
README.md FILE 237
这依赖于字符[
、]
、,
和"
未出现在文件名中,这不是一个安全的假设。
paste
还可以并排排列多个输入。为此,我们可以完全删除 JSON 结构,并输出原始行(向 @muru 致敬):
jq -r '.children.values[]|.path.components[0],.type,.size' | paste - - -
paste - - -
表示 3 列,全部从同一源读取。这次,唯一的假设是文件名不包含换行符。
答案3
jq
可以将其输出呈现为多种格式:请参阅https://stedolan.github.io/jq/manual/#Formatstringsandescaping
对于制表符分隔的输出:
$ jq -r '.children.values[] | [.path.name, .type, .size] | @tsv' file.json
.gitignore FILE 224
Jenkinsfile FILE 1396
README.md FILE 237
pom.xml FILE 2548
src DIRECTORY
答案4
一种基于的衬里解决方案jtc
和 xargs:
bash $ jtc -x'<values>l[+0]<size>l[-1]' -y'<name>l' -y'<type>l' -y'<size>l' your.json | xargs -n3
.gitignore FILE 224
Jenkinsfile FILE 1396
README.md FILE 237
pom.xml FILE 2548
bash $
笔记:文件中存在 json 不规则性(并非每个记录中都存在大小键),为了排除它,第一个参数以-x
这种方式构建(仅处理存在大小的那些记录)。