我有一個輸入檔案,其型別可能因陣列而異,預期為以下輸入之一:
[{"version": "1.0"}]
{version: "1.0"}
如何為輸出構建 jq 運算式以始終轉換為陣列。我想出了以下內容:
jq 'if (select(has("version")?)) then [.] else . end'
一旦version鍵匹配,物件被添加到陣列中,但如果不匹配,則意味著它已經是一個陣列,沒有列印任何內容,我希望它按原樣列印。請建議正確的方法來實作它。
uj5u.com熱心網友回復:
您可以type直接檢查輸入:
jq 'if type == "object" then [.] else . end'
演示
或者使用解構替代運算子?//(自jq 1.6起可用):
jq '. as [$v] ?// $v | [$v]'
演示
uj5u.com熱心網友回復:
對 pmf 的回答的輔助,為什么這不起作用?
input.jsonl:
[{"version": "1.0"}]
{"version": "2.0"}
命令:
jq -c 'if (select(has("version")?)) then [.] else . end'
實際輸出:
[{"version": "2.0"}]
期望的輸出:
[{"version": "1.0"}]
[{"version": "2.0"}]
首先,select過濾掉值。對于輸入到 的每個值select,它會評估您為其輸入提供的過濾器,如果該過濾器評估為真值,則它發出的整個輸入值保持不變。否則沒有輸出。select在這里使用沒有幫助,因為您需要條件的真值或假值if。如果if-then-else運算式的條件部分不發出任何輸出,則整個if-then-else運算式不發出任何輸出。
一種更徹底的理解方式select(expr)是,每次expr發出一個真值,然后select(expr)發出它的輸入值。一種更徹底的理解方式if cond then a else b end是,每次cond發出真值時整體if-then-else發出a,每次cond發出假值時整體if-then-else發出b。
好的,所以忘記select......為什么這不起作用?
命令:
jq -c 'if (has("version")?) then [.] else . end'
實際輸出:
[{"version": "2.0"}]
在這種情況下,?是錯誤抑制運算子,并且相當于try has("version")which 本身相當于try has("version") catch empty。這意味著當發生錯誤時,運算式回傳empty,這意味著沒有輸出。當輸入是串列而不是物件時,確實會發生錯誤。當if-then-else運算式的條件部分沒有輸出時,你猜對了,整個運算式沒有輸出。
你可以通過這樣做來完成這項作業:
命令:
jq -c 'if (try has("version") catch false) then [.] else . end'
實際輸出:
[{"version":"1.0"}]
[{"version":"2.0"}]
當然,這有點繞。你應該遵循 pmf 的回答。但這也許可以幫助您理解為什么您的嘗試沒有按預期進行。
根據經驗,盡量確保您的select和if條件始終為每個輸入發出一個輸出 - 這樣您就不會感到驚訝。可以發出零輸出(例如expr?或select(...))或多輸出(例如.[])的運算式在用作selector 中的條件時會造成混淆if。
uj5u.com熱心網友回復:
arrays如果輸入是陣列,則該函式選擇該輸入。結合//你可以處理它不是的情況:
$ jq -c 'arrays // [.]' versions.json
[{"version":"1.0"}]
[{"version":"2.0"}]
在哪里versions.json:
[{"version":"1.0"}]
{"version":"2.0"}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/363341.html
下一篇:遍歷鏈接物件
