Как напечатать конкретное значение массива с учетом условия в jq, если ключ не указан

#json #kubernetes #select #jq

Вопрос:

Я пытаюсь вывести значение для .metadata.name затем следует имя учащегося в массиве .spec.template.spec.containers[].students[] с использованием функции regex test() в jq.

У меня возникли проблемы с получением отдельного значения массива, так как для массива students[] не указан ключ.

Например, если я проверю массив students [], содержит ли он слово «Джефф», я хотел бы, чтобы вывод отображался, как показано ниже:

 student-deployment:    Jefferson
 

Что я пробовал:

Я попробовал команду ниже, которая несколько работает, но я не уверен, как получить только значение «Джефферсон». Приведенная ниже команда выведет все значения массива students [], что мне не нужно. Я использую Powershell для выполнения приведенной ниже команды.

 kubectl get deployments -o json | jq -r '.items[] | select(.spec.template.spec.containers[].students[]?|test(""^Jeff."")) | .metadata.name, "":t"", .spec.template.spec.containers[].students'
 

Есть ли способ вывести конкретное значение массива с учетом условия в jq, если ключ не указан? Кроме того, будет ли решение работать при наличии нескольких развертываний?

Приведенный ниже шаблон развертывания выполнен в формате json, и я сократил его только до соответствующих частей.

 {
    "apiVersion": "v1",
    "items": [
        {
            "apiVersion": "apps/v1",
            "kind": "Deployment",
            "metadata": {
                "name": "student-deployment",
                "namespace": "default"
            },
            "spec": {
                "template": {
                    "spec": {
                        "containers": [
                            {
                                "students": [
                                        "Alice",
                                        "Bob",
                                        "Peter",
                                        "Sally",
                                        "Jefferson"
                                ]
                            }
                        ]
                    }
                }
            }
        }
    ]
}
 

Ответ №1:

Для этого подхода мы вводим переменную $pattern . Вы можете установить его в --arg pattern свое регулярное выражение, например "Jeff" "^Al" , или "e$" отфильтровать список учащихся test , или оставить его пустым, чтобы увидеть всех учащихся.

Теперь мы повторяем все .item[] элементы (т. е. «все развертывания»). Для каждого найденного мы выводим содержимое .metadata.name , за которым следует буквальное двоеточие и пробел. Затем мы повторяем все снова .spec.template.spec.containers[].students[] , выполняем шаблон test и объединяем результат.

Чтобы распечатать необработанные строки вместо JSON, мы используем эту -r опцию при вызове jq .

 kubectl get deployments -o json 
| jq --arg pattern "Jeff" -r '
    .items[]
    | .metadata.name   ": "   (
        .spec.template.spec.containers[].students[]
        | select(test($pattern))
      )
  '
 

Комментарии:

1. Спасибо! Это сработало отлично. Могу ли я узнать, можно ли добиться того же с помощью запроса JSONPath? Для моего запроса JSONPath я попытался выполнить запрос ниже: kubectl get deployment -o=jsonpath="{range .items[?(@.spec.template.spec.containers[*].students[*])]}{'n'}{.metadata.name}{':t'}{range .spec.template.spec.containers[*]}{.students[?(@=="Alice")]}{end}{end}" Но это работает только для оценки соответствия слов. Можно ли было бы использовать JSONPath для запроса этого, поскольку я читал, что регулярное выражение JSONPath =~ не работает?

2. @calmmash Извините, я абсолютно ничего не знаю о kubernetes/kubectl и его опциях (на самом деле, в своем ответе я просто повторил ваш вызов и попросил jq выполнить дальнейшую обработку). Подумайте о том, чтобы задать новый вопрос, посвященный именно этой проблеме, чтобы привлечь внимание экспертов kubernetes/kubectl.

3. Ладно, не беспокойся. Спасибо.

Ответ №2:

Чтобы получить массив(ы) «студенты» во входных данных, вы можете использовать этот фильтр:

 .items[]
| paths(objects) as $p
| getpath($p)
| select( objects | has("students") )
| .students
 

Затем вы можете добавить дополнительные фильтры для выбора конкретного учащегося(ов), представляющего интерес, например

 | .[]
| select(test("Jeff"))
 

А затем добавьте любые фильтры постобработки, например

 | "student-deployment: (.)"
 

Конечно, вы можете получить students массив множеством других способов.