Bash

將 json 文件轉換為“key-path”,結果值位於每個“key-path”的末尾

  • April 26, 2019

我有一個較大且相對複雜的 json 配置文件,我想使用“grep”等簡單工具搜尋鍵和/或值。當我“grep”時,我希望輸出中的文件包含鍵的完整路徑以及通向最終值的每個子鍵/數組。

這類似於在大型文件系統中搜尋文件/目錄,並且能夠在找到文件/目錄時查看文件/目錄的完整路徑,例如使用“查找”命令。

此外,與我想要完成的類似比較是 xml2 實用程序,它將 xml 文件轉換為鍵/值路徑,以便於搜尋和報告。

我一直在使用“jq”實用程序來使用“keys”命令解析 json 文件。我拼湊了一個粗略的 bash 腳本來遍歷 json 鍵路徑的第一個分支——但找不到一種簡單的方法來遞歸地遍歷整個 json 結構樹。

這是我在 bash 腳本中嘗試執行的操作的手動說明。是的,它的效率非常低,但我想我會在提高性能之前讓它工作!

給定包含複雜配置的 file.json,我使用鍵來獲取第一個項目,一旦有了它,我就在另一個迭代中使用它來獲取下一個鍵,依此類推,直到我到達分支的末尾……

cat file.json | jq '. | keys | .[]'
cat file.json | jq '.Blueprints | keys | .[]'
cat file.json | jq '.Blueprints.security | keys | .[]'
cat file.json | jq '.Blueprints.security.kerberos_descriptor | keys | .[]'
cat file.json | jq '.Blueprints.security.kerberos_descriptor.identities | keys | .[]'

最終結果最終如下所示:

."Blueprints"."security"."kerberos_descriptor"."identities"[0]."keytab"."configuration"."cluster-env/smokeuser_keytab"

但當然,這只是一個非常大的鍵/值樹的第一個分支。

jq有一些合適的內置函式可以提供幫助。你不需要太多的 Bash 技巧,它也不是很適合這個問題。這是 jq 中一個非常明確的版本,您應該可以根據需要進行修改:

jq -r '. as $root |
      path(..) | . as $path |
      $root | getpath($path) as $value |
      select($value | scalars) |
      ([$path[] | @json] | join(".")) + " = " + ($value | @json)
   ' < file.json

它多次使用變數綁定運算符來按名稱記住計算值 - 其中一些是不必要的,但它們更容易討論。... as $identifier |這些行中的每一行都將$x程序其餘部分的變數綁定到左側的值。

path/1函式是這裡的關鍵,並且基本上已經完成了您想要的操作:path(..)生成一個包含您需要遍歷的所有鍵的數組,以獲取嵌套在對像中的每個值。每條路徑的形式為

[ "Blueprints", "security", "kerberos_descriptor" ]

它們可以像其他數組一樣使用,也可以與解釋路徑的特殊函式一起使用。

path(..) | . as $path |

特別是定義一個循環:對於文件中的每個路徑,呼叫它$path並將程序的其餘部分作為循環體執行。程序的其餘部分是選擇和輸出,因此對於每條路徑,都會檢查它並可能生成一條輸出線。

getpath讀取其中一個路徑數組並提取它標識的值。select讓我們過濾到僅通過測試的值 - 在這裡,它僅選擇量值(數字、字元串或布爾值或空值),因此中間對象和數組被排除在外(空值也是如此)。

最後一行將輸出格式化為

"abc"."def".3."xyz" = true

對於文件中的每個值,每行一個,您可以根據需要進行調整。將其重定向到一個文件中,您可以grep重複通過它。

@json正確引用值,其餘的應該很容易更改以適合您需要的格式。它不對數組使用方括號,因為join在其他情況下手動複製將點放入的功能非常複雜。兩邊都需要括號。

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