如何用sed替换yml文件中的文本以确保保留缩进

时间:2019-07-03 12:43:54

标签: awk sed yaml indentation

我有一个YAML文件,其内容如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: castlereport-cfg
  namespace: qa
data:
  application.properties: |
    BODY

我需要用application.properties文件内容替换BODY。我使用sed来做到这一点:

sed -i -e '/BODY/r target/classes/application-dev.properties' -e 's///' -e '/^ *\$/d'  target/classes/$kubeConfigFile

它完成了我所需要的,但是却缩进了,我得到的是:

apiVersion: v1
kind: ConfigMap
metadata:
  name: castlereport-cfg
  namespace: qa
data:
  application.properties: |

server.port=8080
server.context-path=/

spring.main.banner-mode=off
logbook.format.style=http

我应该怎么做才能缩进?

sed命令中-e '/^ *\$/d'部分的另一项内容是删除空白行,但这似乎也不起作用。

预期输出如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: castlereport-cfg
  namespace: qa
data:
  application.properties: |
    server.port=8080
    server.context-path=/
    spring.main.banner-mode=off
    logbook.format.style=http   

更新: 我有一个Jenkins管道脚本,可以通过以下三行实现我想要的功能:

   sh ( script : "sed -i -e 's/^[ \t\$]*/   /' -e \"/^ *\$/d\"  ./target/classes/"+configFile, returnStdout: true).trim() //remove trailing spaces and blank lines
   sh ( script : "sed -i -e \"/BODY/r ./target/classes/"+configFile+"\" -e \"s///\" ./target/classes/" + configMapKubernetes, returnStdout: true).trim() // insert content of application-dev.properties to YAML file using BODY
   sh ( script : "sed -i -e \"/^ *\$/d\"  ./target/classes/" + configMapKubernetes, returnStdout: true).trim() //remove  blank lines

管道脚本具有通用性,因此整个命令都在双引号内。

3 个答案:

答案 0 :(得分:2)

sed用于对单个字符串全部进行简单的s / old / new。这个awk脚本可能就是您想要的:

$cat tst.awk
NR==FNR {
    rec[++numLines] = $0
    next
}
s = index($0,"BODY") {
    indent = sprintf("%*s",s-1,"")
    for (lineNr=1; lineNr<=numLines; lineNr++) {
        print indent rec[lineNr]
    }
    next
}
{ print }

例如,给定以下输入文件:

$ cat foo.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: castlereport-cfg
  namespace: qa
data:
  application.properties: |
    BODY

$ cat props
here is some text
    split across
  a few lines

我们可以这样做,它使用yaml文件中的BODY缩进,但还保留了props文件中的所有其他缩进:

$ awk -f tst.awk props foo.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: castlereport-cfg
  namespace: qa
data:
  application.properties: |
    here is some text
        split across
      a few lines

如果您想忽略props文件中的缩进,并将所有道具文本放在BODY开始的地方,那是一个简单的调整:

$ cat tst.awk
NR==FNR {
    sub(/^[[:space:]]+/,"")
    rec[++numLines] = $0
    next
}
s = index($0,"BODY") {
    indent = sprintf("%*s",s-1,"")
    for (lineNr=1; lineNr<=numLines; lineNr++) {
        print indent rec[lineNr]
    }
    next
}
{ print }

$ awk -f tst.awk props foo.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: castlereport-cfg
  namespace: qa
data:
  application.properties: |
    here is some text
    split across
    a few lines

答案 1 :(得分:1)

这可能对您有用(GNU sed):

sed -E 's/^(\s*)BODY/sed "\/\\S\/!d;s#^#\1#" propertyFile/e' file

此解决方案用另一个sed调用替换了包含BODY的行,该sed调用将BODY之前的空格添加到属性文件的每一行。空行也将从属性文件中删除。如果还要从原始文件中删除空行,请使用:

sed -E '/\S/!d;s/^(\s*)BODY/sed "\/\\S\/!d;s#^#\1#" propertyFile/e' file

答案 2 :(得分:-1)

这就是我最终为了获得所需的东西而做的事情。尽管埃德·莫顿(Ed Morton)的答案也能胜任,但我更喜欢使用更少行的版本:

sed -i -e 's/^[ \t\$]*/    /' -e '/^ *\$/d'  target/classes/application-dev.properties
sed -i -e '/BODY/r target/classes/application-dev.properties' -e 's///' -e '/^ *\$/d'  target/classes/$kubeConfigFile

因此没有像“保留”缩进一样的东西。您只是按自己的方式缩进