使用JQ和bash构建新的JSON

时间:2018-06-18 21:22:59

标签: json bash jq

我正在尝试使用bash从头开始创建JSON。

最终结构必须如下:

{
  "hosts": {
    "a_hostname" : {
      "ips" : [
          1,
          2,
          3
      ]
    },
    {...}
  }
}

首先,我创建一个格式为

的输入文件
hostname ["1.1.1.1","2.2.2.2"]
host-name2 ["3.3.3.3","4.4.4.4"]

这是由以下人员创建的:

for host in $( ansible -i hosts all --list-hosts ) ; \
    do echo -n "${host} " ; \
    ansible -i hosts $host -m setup | sed '1c {' | jq -r -c '.ansible_facts.ansible_all_ipv4_addresses' ; \
done > hosts.txt

这里的关键点是IP列表/数组来自JSON文件并由jq提取。此提取输出已经有效/引用的JSON数组,但是作为txt文件中的字符串。

接下来我使用jq将整个文本文件解析为所需的JSON:

jq -Rn '
    { "hosts": [inputs |
        split("\\s+"; "g") |
        select(length > 0 and .[0] != "") |
        {(.[0]):
            {ips:.[1]}
        }
    ] | add }
' < ~/hosts.txt

这几乎是正确的,除了被视为字符串并引用的IP值之外的所有内容都导致:

{
    "hosts": {
        "hostname1": {
            "ips": "[\"1.1.1.1\",\"2.2.2.2\"]"
        },
        "host-name2": {
            "ips": "[\"3.3.3.3\",\"4.4.4.4\"]"
        }
    }
}

我现在陷入了最后的障碍 - 如何插入IP而不会再引用它们。

修改 - 使用{ips: .[1] | fromjson }}代替{ips:.[1]}解决引用问题。 然而,@ CharlesDuffy的帮助suggesting converting to TSV完全否定了这一点。

原Q体:

到目前为止,我已经

jq -n {hosts:{}} | \
for host in $( ansible -i hosts all --list-hosts ) ; \
    do jq ".hosts += {$host:{}}" | \
    jq ".hosts.$host += {ips:[1,2,3]}" ; \
done ;

[1,2,3]实际上是来自一个子shell,但包含它似乎是不必要的,因为该部分有效,并使其更难阅读)

这种作品,但似乎有两个问题。

1)最终输出中只有一个主机,其中包含列表中第一个主机的数据(即使第二个问题被绕过,这仍然存在):

{
  "hosts": {
    "host_1": {
      "ips": [
        1,
        2,
        3
      ]
    }
  }
}

2)其中一个主机名中有-,导致jq出现语法错误和编译错误。我一直坚持报价地狱试图让它被解释,但也被引用。救命啊!

感谢您的任何意见。

1 个答案:

答案 0 :(得分:3)

假设您的输入格式为:

host_1 1 2 3
host_2 2 3 4
host-with-dashes 3 4 5
host-with-no-addresses

... re:编辑指定不同的格式:将@tsv添加到JQ命令中,生成现有格式以生成此格式。

如果您想将其转换为相关格式,则可能如下所示:

jq -Rn '
{ "hosts": [inputs |
            split("\\s+"; "g") |
            select(length > 0 and .[0] != "") |
            {(.[0]): .[1:]}
           ] | add
}' <input.txt

作为输出产生的结果:

{
  "hosts": {
    "host_1": [
      "1",
      "2",
      "3"
    ],
    "host_2": [
      "2",
      "3",
      "4"
    ],
    "host-with-dashes": [
      "3",
      "4",
      "5"
    ],
    "host-with-no-addresses": []
  }
}