【问题标题】:How do I print a specific value of an array given a condition in jq if there is no key specified如果没有指定键,如何在 jq 中打印给定条件的数组的特定值
【发布时间】:2021-09-20 20:20:57
【问题描述】:

我正在尝试使用 jq 中的正则表达式 test() 函数在 .spec.template.spec.containers[].students[] 数组中输出 .metadata.name 的值,后跟学生的姓名。

我在检索单个数组值时遇到了麻烦,因为没有为 students[] 数组指定键。

例如,如果我检查 students[] 数组是否包含单词“Jeff”,我希望输出显示如下:

student-deployment:    Jefferson

我尝试过的:

我已经尝试了下面的命令,该命令有些工作,但我不确定如何仅获取“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"
                                ]
                            }
                        ]
                    }
                }
            }
        }
    ]
}

【问题讨论】:

    标签: json kubernetes select jq


    【解决方案1】:

    对于这个方法,我们引入了一个变量$pattern。您可以使用--arg pattern 将其设置为您的正则表达式,例如"Jeff""^Al""e$" 让学生列表按test 过滤,或留空以查看所有学生。

    现在,我们遍历所有 .item[] 元素(即遍历“所有部署”)。对于每个找到的内容,我们输出.metadata.name 的内容,后跟一个文字冒号和一个空格。然后我们再次遍历所有 .spec.template.spec.containers[].students[],执行模式 test 并连接结果。

    要打印出原始字符串而不是 JSON,我们在调用 jq 时使用 -r 选项。

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

    【讨论】:

    • 谢谢!这工作得很好。我可以知道是否也可以使用 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 正则表达式 =~ 不起作用?
    • @calmmash 对不起,我对 kubernetes/kubectl 及其选项一无所知(实际上,在我的回答中,我只是复制了您对它的调用并让 jq 进行后续处理)。考虑提出一个针对该问题的新问题,以引起 kubernetes/kubectl 专家的注意。
    • 好的,不用担心。谢谢。
    【解决方案2】:

    要检索输入中的“学生”数组,您可以使用此过滤器:

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

    然后您可以添加其他过滤器来选择感兴趣的特定学生,例如

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

    然后添加任何后处理过滤器,例如

    | "student-deployment: \(.)"
    

    当然,您可以通过多种其他方式获取students 数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 2015-09-28
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 2019-01-04
      相关资源
      最近更新 更多