jq:将数组转换为按文件名索引的对象吗?

时间:2018-07-06 20:11:09

标签: json jq pathname

如何使用jq将数组转换为按文件名索引的对象,或将多个文件读入按文件名索引的对象?

例如

jq -s 'map(select(.roles[]? | contains ("mysql")))' -C dir/file1.json dir/file2.json

这给了我我想要的数据,但是我需要知道它们来自哪个文件。

所以不是

[
    { "roles": ["mysql"] },
    { "roles": ["mysql", "php"] }
]

对于输出,我想要:

{
    "file1": { "roles": ["mysql"] },
    "file2": { "roles": ["mysql", "php"] }
}

如果可能,我确实希望将“ .json”文件扩展名也剥离掉, ,而只是去除基名(不包括dir)。


示例

file1.json
{ "roles": ["mysql"] }
file2.json
{ "roles": ["mysql", "php"] }
file3.json
{ }

我的真实文件中显然还包含其他内容,但这对于本示例来说已经足够了。 file3只是为了证明有时会丢失“角色”。

换句话说:我正在尝试在“角色”列表中查找包含“ mysql”的文件。我需要将文件名和内容组合到一个JSON对象中。


为进一步简化问题,

jq 'input_filename' f1 f2

为我提供所有想要的文件名,但是我不知道如何将它们组合成一个对象或数组。

jq -s 'map(input_filename)' f1 f2

给我相同的文件名,每个文件重复一次。例如[ "f1", "f1" ]代替[ "f1", "f2" ]

2 个答案:

答案 0 :(得分:1)

jq 方法:

jq 'if (.roles[] | contains("mysql")) then {(input_filename | gsub(".*/|\\.json$";"")): .}
    else empty end' ./file1.json ./file2.json | jq -s 'add'

预期输出:

{
  "file1": {
    "roles": [
      "mysql"
    ]
  },
  "file2": {
    "roles": [
      "mysql",
      "php"
    ]
  }
}

答案 1 :(得分:1)

如果jq具有inputs(jq 1.5也是如此),则只需调用一次jq即可完成任务。 另外,使用any可能比遍历.roles的所有元素更有效。

技巧是使用-n选项调用jq,例如

jq -n '
  [inputs
   | select(.roles and any(.roles[]; contains("mysql")))
   | {(input_filename | gsub(".*/|\\.json$";"")): .}]
  | add' file*.json