Jq regex test() выбирает неожиданные значения

Я пытаюсь проанализировать JSON из aws ecr describe-images и вернуть результат с определенным тегом изображения, соответствующим шаблону, из списка. В частности, я получаю массив со многими из этих записей:

{
  "imageDetails": [
    {
      "registryId": "997652729005",
      "repositoryName": "events",
      "imageDigest": "sha256:5b649219a3abc5e903b27fd947f375df8634c883432a69e40d245ac2393d67b2",
      "imageTags": [
        "events-test-build-340"
      ],
      "imageSizeInBytes": 314454408,
      "imagePushedAt": "2021-01-12T10:42:51-05:00",
      "imageScanStatus": {
        "status": "COMPLETE",
        "description": "The scan was completed successfully."
      },
      "imageScanFindingsSummary": {
        "imageScanCompletedAt": "2021-01-12T10:43:00-05:00",
        "vulnerabilitySourceUpdatedAt": "2021-01-12T04:45:25-05:00",
        "findingSeverityCounts": {}
      },
      "imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "artifactMediaType": "application/vnd.docker.container.image.v1+json"
    },
    {
      "registryId": "997652729005",
      "repositoryName": "events",
      "imageDigest": "sha256:0fae259bcfe02c8cf0ec3746aae668b3166960e7119467496df9aedfbc2c8c5b",
      "imageTags": [
        "6debaabc26cc82a4011ea9c71854cebac7a57250-433",
        "6debaabc26cc82a4011ea9c71854cebac7a57250",
        "6debaabc26cc82a4011ea9c71854cebac7a57250-433-dev",
        "events-prod-build-433"
      ],
      "imageSizeInBytes": 316110570,
      "imagePushedAt": "2020-12-21T03:11:52-05:00",
      "imageScanStatus": {
        "status": "COMPLETE",
        "description": "The scan was completed successfully."
      },
      "imageScanFindingsSummary": {
        "imageScanCompletedAt": "2020-12-21T03:12:02-05:00",
        "vulnerabilitySourceUpdatedAt": "2020-11-03T20:21:09-05:00",
        "findingSeverityCounts": {}
      },
      "imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "artifactMediaType": "application/vnd.docker.container.image.v1+json"
    }
  ]
}

Я хотел бы, чтобы вывод был примерно таким:

{
  "tag": [
    "6debaabc26cc82a4011ea9c71854cebac7a57250"
  ],
  "sha": "sha256:5b649219a3abc5e903b27fd947f375df8634c883432a69e40d245ac2393d67b2",
  "imagePushedAt": "2021-01-12T10:42:51-05:00"
}

Задача состоит в том, чтобы выбрать изображения с тегом, имя которого включает *prod-build* (развернутая производственная сборка), но затем вернуть тег без тире, который мы фактически используем. (Да, это совсем ущербно, я знаю).

Я продвинулся довольно далеко:

cat ecr-describe-images-events.json 
  | jq '.imageDetails[] 
  | {tag: .imageTags, sha: .imageDigest, date_pushed: .imagePushedAt} 
  | select( .tag | contains(["prod-build"])) 
  .tag[] |= walk(
    if type= = "string" then 
      select(
        match("^[^-]+$")
      ) 
    else 
      null 
    end
  )'

Итак, из массива imageDetails получаем и именуем элементы, затем из массива тегов выбираем узлы, у которых есть тег со строкой prod-build. Из этих узлов найдите
tags элемент массива, имя которого не содержит тире, и вернуть его.

Последняя часть, которую я сделал с select, walk и match, ведет себя иначе, чем я ожидал. Я осознаю:

{
  "tag": [
    "events-test-build-340"
  ],
  "sha": "sha256:5b649219a3abc5e903b27fd947f375df8634c883432a69e40d245ac2393d67b2",
  "date_pushed": "2021-01-12T10:42:51-05:00"
}
{
  "tag": [
    "6debaabc26cc82a4011ea9c71854cebac7a57250",
    "events-prod-build-433",
    null,
    null
  ],
  "sha": "sha256:8638389b7d83869b17b1c74ff30740d7cf8eff4574100c1270f20d4686252552",
  "date_pushed": "2021-02-17T13:11:42-05:00"
}

Если я не включу последнюю часть, начиная walk(...) я получаю правильные узлы. Но когда я использую walk с совпадением или тестом, я возвращаю элементы массива, которые не соответствуют моему регулярному выражению.

Я не зациклен на своем подходе или формате вывода: мне просто нужны три поля в какой-то структуре. Что я не понял?

Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
0
122
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Кажется, вы хотите s.t. нравиться:

jq '.imageDetails[] 
  | {tag: .imageTags, sha: .imageDigest, date_pushed: .imagePushedAt} 
  | select( any(.tag[]; test("prod-build")?))
  | .tag |= map(select(test("^[^-]+$")? ))'

Вам придется настроить это, если вы хотите избежать выбора каких-либо объектов, для которых .tag в противном случае был бы пустым массивом.

Вот вариант использования contains для обеих проверок, при этом вторая проверка отрицается с помощью not:

jq '.imageDetails[] | select(.imageTags | any(contains("prod-build"))) | {
  tag: .imageTags | map(select(contains("-") | not)),
  sha: .imageDigest,
  date_pushed: .imagePushedAt
}'
{
  "tag": [
    "6debaabc26cc82a4011ea9c71854cebac7a57250"
  ],
  "sha": "sha256:0fae259bcfe02c8cf0ec3746aae668b3166960e7119467496df9aedfbc2c8c5b",
  "date_pushed": "2020-12-21T03:11:52-05:00"
}

Демо

Ответ принят как подходящий

Вы можете использовать del, чтобы удалить все теги, соответствующие определенному критерию:

.imageDetails[]
| {
    tag: .imageTags,
    sha: .imageDigest,
    date_pushed: .imagePushedAt
}
| select(.tag | contains(["prod-build"]))
| del(.tag[] | select(contains("-")))

Сначала выбирает те объекты с тегом "prod-build", а затем удаляет все остальные теги из списка.

Выход:

{
  "tag": [
    "6debaabc26cc82a4011ea9c71854cebac7a57250"
  ],
  "sha": "sha256:0fae259bcfe02c8cf0ec3746aae668b3166960e7119467496df9aedfbc2c8c5b",
  "date_pushed": "2020-12-21T03:11:52-05:00"
}

Все хорошие ответы; ваш выигрывает как самый простой и читаемый. Спасибо!

Tom Harrison 08.12.2022 09:12

Другие вопросы по теме