3 回答

TA貢獻1847條經驗 獲得超11個贊
首先,獲取一個包含對象數組輸入中所有不同對象屬性名稱的數組。這些將是CSV的列:
(map(keys) | add | unique) as $cols
然后,對于對象數組輸入中的每個對象,將獲得的列名映射到對象中的相應屬性。這些將是CSV的行。
map(. as $row | $cols | map($row[.])) as $rows
最后,將列名放在行之前,作為CSV的標題,然后將結果行流傳遞到@csv過濾器。
$cols, $rows[] | @csv
現在都在一起了。請記住使用該-r標志將結果作為原始字符串獲?。?/p>
jq -r '(map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $cols, $rows[] | @csv'

TA貢獻1805條經驗 獲得超10個贊
瘦的
jq -r '(.[0] | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv'
要么:
jq -r '(.[0] | keys_unsorted) as $keys | ([$keys] + map([.[ $keys[] ]])) [] | @csv'
細節
在旁邊
描述細節是棘手的,因為jq是面向流的,這意味著它對JSON數據序列(而不是單個值)進行操作。輸入的JSON流將轉換為某種內部類型,并通過過濾器傳遞,然后在程序末尾的輸出流中進行編碼。內部類型不是由JSON建模的,并且不以命名類型存在。最簡單的方法是檢查裸索引(.[])或逗號運算符的輸出(可以通過調試器直接檢查它,但這是基于jq的內部數據類型,而不是JSON背后的概念數據類型) 。
$ jq -c'。[]'<<<'[“ a”,“ b”]'
“一種”
“ b”
$ jq -cn'“ a”,“ b”'
“一種”
“ b”
請注意,輸出不是數組(應該是["a", "b"])。緊湊輸出(該-c選項)表明,每個數組元素(或,過濾器的參數)在輸出中均成為單獨的對象(每個元素在單獨的行上)。
流就像JSON-seq一樣,但是在編碼時使用換行符而不是RS作為輸出分隔符。因此,此內部類型在此答案中由通用術語“序列”指代,其中“流”保留用于編碼的輸入和輸出。
構造過濾器
可以使用以下命令提取第一個對象的鍵:
.[0] | keys_unsorted
密鑰通常會保持其原始順序,但不能保證保留確切的順序。因此,將需要使用它們對對象建立索引以按相同順序獲取值。如果某些對象的鍵順序不同,這也可以防止將值放在錯誤的列中。
為了將鍵作為第一行輸出并使它們可用于索引,它們都存儲在變量中。然后,管道的下一個階段將引用此變量,并使用逗號運算符將標頭添加到輸出流之前。
(.[0] | keys_unsorted) as $keys | $keys, ...
逗號后的表達有點牽連。對象上的索引運算符可以采用字符串序列(例如"name", "value"),返回這些字符串的屬性值序列。$keys是一個數組,而不是一個序列,因此[]可以將其轉換為序列,
$keys[]
然后可以傳遞給 .[]
.[ $keys[] ]
這也產生一個序列,因此使用數組構造函數將其轉換為數組。
[.[ $keys[] ]]
該表達式將應用于單個對象。map()用于將其應用于外部數組中的所有對象:
map([.[ $keys[] ]])
最后,在此階段,它被轉換為序列,因此每個項目在輸出中成為單獨的行。
map([.[ $keys[] ]])[]
為什么將序列捆綁到map唯一的數組中以在外部解綁呢?map產生一個數組;.[ $keys[] ]產生一個序列。將mapfrom 應用于序列.[ $keys[] ]會產生一個值序列數組,但是由于序列不是JSON類型,因此您將獲得一個包含所有值的扁平數組。
["NSW","AU","state","New South Wales","AB","CA","province","Alberta","ABD","GB","council area","Aberdeenshire","AK","US","state","Alaska"]
每個對象的值需要保持分開,以便它們在最終輸出中成為單獨的行。
最后,序列通過@csv格式化程序傳遞。
備用
這些項目可以分離得較晚,而不是早期。代替使用逗號運算符獲取序列(將序列作為正確的操作數傳遞),標頭序列($keys)可以包裝在數組中,并+用于附加值數組。在傳遞給之前,仍然需要將其轉換為序列@csv。

TA貢獻1817條經驗 獲得超6個贊
以下過濾器稍有不同,它將確保將每個值都轉換為字符串。(注意:使用jq 1.5+)
# For an array of many objects
jq -f filter.jq (file)
# For many objects (not within array)
jq -s -f filter.jq (file)
過濾: filter.jq
def tocsv($x):
$x
|(map(keys)
|add
|unique
|sort
) as $cols
|map(. as $row
|$cols
|map($row[.]|tostring)
) as $rows
|$cols,$rows[]
| @csv;
tocsv(.)
- 3 回答
- 0 關注
- 1207 瀏覽
添加回答
舉報