將 json 文件轉換為“key-path”,結果值位於每個“key-path”的末尾
我有一個較大且相對複雜的 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
在其他情況下手動複製將點放入的功能非常複雜。兩邊都需要括號。