Shell

在 shell 腳本中循環遍歷 JSON 數組

  • January 9, 2019

下面是 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

對於問題中提供的案例,@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'

引用自:https://unix.stackexchange.com/questions/477210