从ec2instances.info解析EC2按需定价

时间:2016-06-29 23:20:34

标签: jq

我正在尝试使用curljq来解析AWS EC2按需定价并构建适合在Terraform模块中使用的JSON映射。

我提出的脚本看起来像这样,但它似乎不正确:

curl --silent --show-error 'https://raw.githubusercontent.com/powdahound/ec2instances.info/master/www/instances.json' |
jq '.[]
    | .instance_type as $instance_type
    | (.pricing | keys) as $keys 
    | [.pricing[].linux.ondemand | .] as $values
    | reduce range(0; $keys|length) as $i 
        ({}; . + { ($keys[$i] + "|" + $instance_type): $values[$i] })'

我做错了什么?这是一个较小的代码示例来说明问题:

curl --silent --show-error 'https://gist.githubusercontent.com/joshuaspence/0904a6ce25f8830d9ae2eac8fc44fc7a/raw/b24600ab2e536556a74f4dbb45e2ddaa432d430e/sample.json' |
jq '.[]
    | .instance_type as $instance_type
    | (.pricing | keys) as $keys
    | [.pricing[].linux.ondemand | .] as $values
    | reduce range(0; $keys|length) as $i
        ({}; . + { ($keys[$i] + "|" + $instance_type): $values[$i] })'

上述命令的预期输出为:

{
  "ap-south-1|m1.small": "N/A",
  "us-east-1|m1.small": "0.061",
  "sa-east-1|m1.small": "0.058",
  "ap-northeast-2|m1.small": "0.058",
  "ap-southeast-2|m1.small": "0.058",
  "us-west-2|m1.small": "0.044",
  "us-gov-west-1|m1.small": "0.053",
  "us-west-1|m1.small": "0.047",
  "eu-central-1|m1.small": "N/A",
  "eu-west-1|m1.small": "0.047"
}
{
  "ap-south-1|m1.medium": "N/A",
  "us-east-1|m1.medium": "0.087",
  "ap-northeast-1|m1.medium": "0.122",
  "sa-east-1|m1.medium": "0.117",
  "ap-northeast-2|m1.medium": "N/A",
  "ap-southeast-1|m1.medium": "0.117",
  "ap-southeast-2|m1.medium": "0.117",
  "us-west-2|m1.medium": "0.087",
  "us-gov-west-1|m1.medium": "0.106",
  "us-west-1|m1.medium": "0.095",
  "us-central-1|m1.medium": "N/A",
  "us-west-1|m1.medium": "0.095"
}

实际输出是:

{
  "ap-northeast-2|m1.small": "N/A",
  "ap-south-1|m1.small": "0.061",
  "ap-southeast-2|m1.small": "0.058",
  "eu-central-1|m1.small": "0.058",
  "eu-west-1|m1.small": "0.058",
  "sa-east-1|m1.small": "0.044",
  "us-east-1|m1.small": "0.053",
  "us-gov-west-1|m1.small": "0.047",
  "us-west-1|m1.small": "N/A",
  "us-west-2|m1.small": "0.047"
}
{
  "ap-northeast-1|m1.medium": "N/A",
  "ap-northeast-2|m1.medium": "0.087",
  "ap-south-1|m1.medium": "0.122",
  "ap-southeast-1|m1.medium": "0.117",
  "ap-southeast-2|m1.medium": "N/A",
  "eu-central-1|m1.medium": "0.117",
  "eu-west-1|m1.medium": "0.117",
  "sa-east-1|m1.medium": "0.087",
  "us-east-1|m1.medium": "0.106",
  "us-gov-west-1|m1.medium": "0.095",
  "us-west-1|m1.medium": "N/A",
  "us-west-2|m1.medium": "0.095"
}

2 个答案:

答案 0 :(得分:1)

您的脚本提供错误输出的原因是JSON对象的键没有特定的顺序,并且jq内置函数在此顺序方面不稳定。这意味着当您执行(.pricing | keys)[.pricing[].linux.ondemand | .]时,前者中键的顺序与后者中的值的顺序不匹配。

jq程序的简化版本如下:

jq '.[] | .instance_type as $it | .pricing | with_entries(.key |= "\(.)|\($it)" | .value |= .linux.ondemand)'

此jq程序使用with_entries将JSON对象转换为{key, value}个对象的JSON数组,并在重新组装原始对象之前对键值对执行转换。

答案 1 :(得分:0)

以下解决方案使用 keys_unsorted 来保留原始.pricing对象中键的顺序。

    .[]
  | .instance_type as $instance_type
  | .pricing
  | [
        keys_unsorted[] as $k
      | .[$k].linux.ondemand
      | {("\($k)|\($instance_type)"): .}
    ]
  | add