如何用 sed 替换 yml 文件中的文本,确保保留缩进
How to replace a text in yml file with sed making sure that the indentation is preserved
我有一个包含以下内容的 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
管道脚本在 groovy 中,因此整个命令都在双引号内。
sed 用于对单个字符串执行简单的 s/old/new ,即全部 。这个 awk 脚本可能就是您想要的:
$cat tst.awk
NR==FNR {
rec[++numLines] = [=10=]
next
}
s = index([=10=],"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] = [=13=]
next
}
s = index([=13=],"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
这可能适合您 (GNU sed):
sed -E 's/^(\s*)BODY/sed "\/\S\/!d;s#^##" propertyFile/e' file
此解决方案将包含 BODY
的行替换为另一个 sed 调用,该调用将单词 BODY
前的空格附加到 属性 文件中的每一行。空行也从 属性 文件中删除。如果还要从原始文件中删除空行,请使用:
sed -E '/\S/!d;s/^(\s*)BODY/sed "\/\S\/!d;s#^##" propertyFile/e' file
我有一个包含以下内容的 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
管道脚本在 groovy 中,因此整个命令都在双引号内。
sed 用于对单个字符串执行简单的 s/old/new ,即全部 。这个 awk 脚本可能就是您想要的:
$cat tst.awk
NR==FNR {
rec[++numLines] = [=10=]
next
}
s = index([=10=],"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] = [=13=]
next
}
s = index([=13=],"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
这可能适合您 (GNU sed):
sed -E 's/^(\s*)BODY/sed "\/\S\/!d;s#^##" propertyFile/e' file
此解决方案将包含 BODY
的行替换为另一个 sed 调用,该调用将单词 BODY
前的空格附加到 属性 文件中的每一行。空行也从 属性 文件中删除。如果还要从原始文件中删除空行,请使用:
sed -E '/\S/!d;s/^(\s*)BODY/sed "\/\S\/!d;s#^##" propertyFile/e' file