代码之家  ›  专栏  ›  技术社区  ›  Amin Ba

如何在bashshell中读取yaml文件并遍历其中的列表

  •  0
  • Amin Ba  · 技术社区  · 2 年前

    我有这个yaml文件 我有一个yaml文件如下:

    repos:
    - REPO_NAME: A
      INGRESS_SUBDOMAIN: B
      DOCKER_IMAGE_PATH: C
      IMAGE_NAME: D
      MAJOR_VERSION: E
      MINOR_VERSION: F
    
    

    文件名为f.yaml

    在bash中,我想读取文件的内容,然后遍历每个repo,并验证打印字段“a”

    我在做这个,但它不起作用

    #!/usr/bin/bash
    
    file_name="f.yaml"
    for row in $(yq eval '.repos[]' "$file_name"); do
        REPO_NAME=$(echo "$row" | yq eval '.REPO_NAME' -)
        INGRESS_SUBDOMAIN=$(echo "$row" | yq eval '.INGRESS_SUBDOMAIN' -)
        DOCKER_IMAGE_PATH=$(echo "$row" | yq eval '.DOCKER_IMAGE_PATH' -)
        IMAGE_NAME=$(echo "$row" | yq eval '.IMAGE_NAME' -)
        MAJOR_VERSION=$(echo "$row" | yq eval '.MAJOR_VERSION' -)
        MINOR_VERSION=$(echo "$row" | yq eval '.MINOR_VERSION' -)
    
        ECHO $INGRESS_SUBDOMAIN
        ECHO $DOCKER_IMAGE_PATH
        ECHO $IMAGE_NAME
        ECHO $MAJOR_VERSION
        ECHO $MINOR_VERSION
    done
    

    现在它正在打印一堆“null”。如何修复?

    1 回复  |  直到 2 年前
        1
  •  2
  •   Charles Duffy    2 年前

    for row in is unsuitable 当您对其中有空格的值进行迭代时,更不用说换行了。使用 yq --nul-output 和一个 BashFAQ #1 while read 循环:

    while IFS= read -r -d '' repo_yaml; do
      repo_name=$(yq eval '.REPO_NAME' <<<"$repo_yaml")
      # ...and so forth
      echo "repo_name is $repo_name" >&2
    done < <(yq --nul-output '.repos[]' <"$file_name")
    

    或者,更有效,但运行安全风险如果你不相信你的数据不是恶意的,人们可以 use yq -o=shell 生成一个赋值语句,该语句可以 eval ed在任何符合POSIX的shell中一次设置所有变量:

    while IFS= read -r -d '' repo_eval; do
      eval "$repo_eval"
      echo "$REPO_NAME"
      echo "$INGRESS_SUBDOMAIN" # etc
    done < <(yq -o=shell --nul-output '.repos[]' <"$file_name")
    

    然而,如果您的数据可能包含以下内容,这是非常不明智的 PATH: /uploads/evil.com/rootkit:/bin:/usr/bin ; 存在类似的风险 LD_PRELOAD 以及其他特殊值。(您可以通过在yq代码的密钥名称前加一个小写子字符串来减轻这些风险: only all-caps names 对shell和其他POSIX兼容的OS提供的组件具有特殊意义)。