使用 JQ 从刀搜索生成 CSV

使用 JQ 从刀搜索生成 CSV

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(",")'

这:

  1. 扩展数组输入.rows到输出流 ( .rows.[]) 中。
  2. 流动的管道进入下一步(|)。
  3. 将给定的对象扩展为其包含的(在本例中)单个值 ( .[])。
  4. 创建一个数组的结果.name, .["cpu.total"], 和.["memory.total"] 每个都对该对象进行评估( .[ .name, ... ])。
  5. 转换所有值该数组的成字符串( map(tostring))。
  6. 连接元素每个数组都带有逗号 ( 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,多么棒的工具啊!

答案3

表达jq方式

.rows[] | map(.[]) | @csv

你自己的答案很整洁,但是采取迈克尔的担忧关于考虑到键的顺序,您可能希望显式提取所需的值:

.rows[][] | [ .name, ."cpu.total", ."memory.total" ] | @csv

或者,

.rows[] | map( .name, ."cpu.total", ."memory.total" ) | @csv

相关内容