【问题标题】:Replace value of line in yml with Bash用 Bash 替换 yaml 中行的值
【发布时间】:2018-02-15 17:37:53
【问题描述】:

我有以下格式的 yml 文件。

Backendapp:
  Name: spring-rest 
  Image: "testuser/backend"
  ImageTag: "latest"
  ImagePullPolicy: "Always"
  Port: 8080
  replicaCount: 2

Frontendapp:
  Name: spring-js
  Image: "testuser/frontend"
  ImageTag: "latest"
  ImagePullPolicy: "Always"
  replicaCount: 2

如何通过 Bash 替换 Backendapp 的“Image”、“ImageTag”?

编辑:说文件名是 test.yml 上面的内容。然后,我想将 'Image' 和 'ImageTag' 替换为 'Backendapp' 部分的另一个值(比如 'teststring'、'latest2' resp.)。

修改后的文件应如下所示。

Backendapp:
  Name: spring-rest 
  Image: "teststring"
  ImageTag: "latest2"
  ImagePullPolicy: "Always"
  Port: 8080
  replicaCount: 2

Frontendapp:
  Name: spring-js
  Image: "testuser/frontend"
  ImageTag: "latest"
  ImagePullPolicy: "Always"
  replicaCount: 2

【问题讨论】:

  • 除了BackendappFrontendapp之外还有其他板块吗?
  • @RomanPerekhrest 是的.. 其他部分可能会添加不同的名称,但使用相同的键,例如“Image”、“ImageTag”

标签: bash awk sed


【解决方案1】:

关注awk 可能对您有所帮助:

awk '
/:$/{
  flag=""
}
/Backendapp/||/Frontendapp/{
  flag=1
}
flag && NF && (/Image:/||/ImageTag:/){
  match($0,/^[[:space:]]+/);
  val=substr($0,RSTART,RLENGTH);
  $NF="teststring";
  print val $0;
  next
}
1
'   Input_file

输出如下:

Backendapp:
  Name: spring-rest
  Image: teststring
  ImageTag: teststring
  ImagePullPolicy: "Always"
  Port: 8080
  replicaCount: 2

Frontendapp:
  Name: spring-js
  Image: teststring
  ImageTag: teststring
  ImagePullPolicy: "Always"
  replicaCount: 2

解决方案二:根据 OP,OP 也需要将 shell 变量放入 awk 变量中,然后以下可能会有所帮助:

awk -v val_shell="$shell_variable" '
/:$/{
  flag=""
}
/Backendapp/||/Frontendapp/{
  flag=1
}
flag && NF && (/Image:/||/ImageTag:/){
  match($0,/^[[:space:]]+/);
  val=substr($0,RSTART,RLENGTH);
  $NF=val_shell;
  print val $0;
  next
}
1
'   Input_file

【讨论】:

  • @AVJ,所以上面的代码会查找BackendappFrontendapp,所以如果您只想查找 1 个字符串,那么您可以从代码中删除它。
  • 谢谢。它正在替换“Image”和“ImageTag”名称,但我希望它替换这些键的值。例如:“图片:最新”应该变成“图片:teststring”
  • @RaviderSingh13 .. 是的,它有效.. 但是“Image”或“ImageTag”字在它们之前丢失了 2 个空格字符
  • 请检查有问题的更新。您的解决方案正在工作..但是对于值被替换的行,缩进会丢失。即,“Image”和“ImageTag”与“Backendapp”一致,在它之前失去了 2 个空格字符。如何保持缩进?
  • @AVJ,现在请检查我的代码,它应该注意缩进,如果有任何疑问,请告诉我。
【解决方案2】:

Awk解决方案:

awk 'NF==1 && /^[^[:space:]]+:/{ f=(/^(Back|Front)endapp:/) }
     f && $1 ~ /^Image(Tag)?:/{ $1="  teststring" }1' test.yml

输出:

Backendapp:
  Name: spring-rest
  teststring: "testuser/backend"
  teststring: "latest"
  ImagePullPolicy: "Always"
  Port: 8080
  replicaCount: 2

Frontendapp:
  Name: spring-js
  teststring: "testuser/frontend"
  teststring: "latest"
  ImagePullPolicy: "Always"
  replicaCount: 2

【讨论】:

    【解决方案3】:

    这是您的解决方案。它基本上使用 SED 进行替换。只需将“START OF SCRIPT”和“END OF SCRIPT”之间的位复制并粘贴到任何 bash 脚本中,然后运行(以下简单说明):

    脚本开始...

    #!/bin/bash
    
    # SED script will be stored here ...
    
    sedscript=/tmp/sedscript.sed
    
    # first argument to script is the parent name ...
    
    parent="${1}"
    
    # second argument to the script is child name...
    
    child="${2}"
    
    # third argument is the value to replace the CHILD value with ...
    
    value="$3"
    
    cat << EOF > "${sedscript}"
    
    # find parent ...
    /^${parent}:.*$/{
    
        p
    
        # load next line into input ...
        n
    
        # another parent found to print it ...
        /^[a-z|A-Z|0-9]\{1\}:.*$/{
    
            # we have found another parent
            # so stop processing ...
    
            b print_default_text
        }
    
        :search_for_child
    
        /^[ |   ]*$child[ | ]*:.*$/{
    
            s/^\([^:]*:[ |\"|   ]*\)[^\"]*\(.*\)$/\1$value\2/p
    
            b dont_print_default_text
        }
    
        p
        n
        b search_for_child
    }
    
    
    :print_default_text
    p
    
    :dont_print_default_text
    

    EOF

    sed -n -f "${sedscript}" "input.yml"
    

    ...脚本结束

    现在我们将脚本保存为 alter.sh(例如)然后像这样运行它(将 Frontendapp/Image 更改为“another-image-name”):

    ./alter.sh Frontendapp Image "another-image-name"

    输入文件 ....

    后端应用程序: 名称:弹簧架 图片:“测试字符串” 图片标签:“最新2” ImagePullPolicy:“总是” 端口:8080 副本数:2

    前端应用程序: 名称:spring-js 图片:“测试用户/前端” 图片标签:“最新” ImagePullPolicy:“总是” 副本数:2

    输出文件 ....

    后端应用程序: 名称:弹簧架 图片:“测试字符串” 图片标签:“最新2” ImagePullPolicy:“总是” 端口:8080 副本数:2

    前端应用程序: 名称:spring-js 图像:“另一个图像名称” 图片标签:“最新” ImagePullPolicy:“总是” 副本数:2

    注意:脚本也会处理引号,即如果原始值有引号,那么新值也会被引号括起来。

    希望这会有所帮助....

    【讨论】:

    • 感谢 Mohammad - 我是新手 ;)
    • 它给了我错误“sed: file /tmp/sedscript.sed line 10: Invalid range end”
    • 我已经编辑过了 - 男生错误。表达式是 'a-z|A-z|..',而它应该是 'a-z|A-Z',即大写的 'Z' 代表 'A-Z' 范围。请再试一次。确保输入文件也有换行符,根据这张票的原始文本。
    • 就像一个魅力......但已经使用了上面建议的 awk 解决方案。
    • AWK 或 SED ...不管...这些实用程序中的任何一个都是老板 ;)
    猜你喜欢
    • 2020-05-12
    • 2016-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-14
    • 1970-01-01
    • 2020-09-05
    • 2015-05-05
    相关资源
    最近更新 更多