![使用 JQ 从刀搜索生成 CSV](https://linux22.com/image/9834/%E4%BD%BF%E7%94%A8%20JQ%20%E4%BB%8E%E5%88%80%E6%90%9C%E7%B4%A2%E7%94%9F%E6%88%90%20CSV.png)
JQ 看起来是一个很棒的工具,但我正在努力使用它。这就是我想要做的:仅从厨师刀搜索中提取值并生成 CSV。
给出这个命令和输出:
Knife 搜索节点 "name:foo*" -a name -a cpu.total -a memory.total -Fj
{ “结果”:2, “行”:[ { “foo-01”:{ “名称”:“foo-01”, “CPU.总计”:12, "内存.总计": "16267368kB" } }, { “foo-02”:{ “名称”:“foo-02”, “CPU.总计”:12, “内存.总计”:“16264296kB” } } ] }
我想将值提取到 CSV,如下所示:
foo-01,12,16267368kB foo-02,12,16264296kB
(我可以处理报价)
答案1
... | jq -r '.rows[] | .[] | [.name, .["cpu.total"], .["memory.total"]] | map(tostring) | join(",")'
这:
- 扩展数组输入
.rows
到输出流 (.rows.[]
) 中。 - 流动的管道进入下一步(
|
)。 - 将给定的对象扩展为其包含的(在本例中)单个值 (
.[]
)。 - 创建一个数组的结果
.name
,.["cpu.total"]
, 和.["memory.total"]
每个都对该对象进行评估(.[ .name, ... ]
)。 - 转换所有值该数组的成字符串(
map(tostring)
)。 - 连接元素每个数组都带有逗号 (
join(",")
)。
jq -r
输出原始数据,而不是引用并转义它。那么输出是:
foo-01,12,16267368kB
foo-02,12,16264296kB
如你所愿。根据您的 CSV 解析器和真实数据,您可能需要在字符串周围添加额外的引号,您可以添加这些引号,或使用@csv
代替最后两个步骤。
... | jq -r '.rows[] | .[] | [.name, .["cpu.total"], .["memory.total"]] | @csv'
map
我们可以通过只转换里面的一个值来跳过,这需要一些额外的括号:
... | jq -r '.rows[]|.[]|[.name, (.["cpu.total"] | tostring), .["memory.total"]] | join(",")'
可能是最丑陋的选择:
... | jq -r '.rows[]|to_entries|.[]|.key + "," + (.value["cpu.total"] | tostring) + "," + .value["memory.total"]'
在这种情况下,我们不依赖该.name
字段,而是手动构建整个字符串。如果您需要高度定制的格式,这是最灵活的选项。
答案2
可能有一个“宇宙规则”,上面写着“一旦你向 SE 发布问题,答案就会出现”......发布这个问题后不久,我坚持使用 try/google/rtfm 循环,并最终想出了这个对我有用的方法:
Knife 搜索节点 "name:foo*" -a name -a cpu.total -a memory.total -Fj | jq -r '.rows[] | jq -r '.rows[] |地图(.[]) | @csv'
返回:
“foo-01”,12,“16267000kB” “foo-02”,12,“16267000kB”
这可以干净地导入到谷歌表格中。我可能可以通过迈克尔给出的一些例子进一步调整这一点。我有点喜欢这个,因为我不必明确指定字段名称。期待更多地使用 JQ,多么棒的工具啊!