给定一个包含以下内容的文件:
pkg1:
replicaCount: 1
image:
tag: latest
pullPolicy: Always
pkg2:
replicaCount: 2
image:
tag: latest
pullPolicy: Always
我想搜索tag
附加到特定包(即pkg1
)的 并替换latest
为其他内容(即junk
),以便我得到:
pkg1:
replicaCount: 1
image:
tag: junk
pullPolicy: Always
pkg2:
replicaCount: 2
image:
tag: latest
pullPolicy: Always
感谢这篇文章的接受答案(查找一个字符串并在找到第一个字符串后替换另一个字符串)我可以使用“ex”来做到这一点:
printf "%s\n" "/pkg1//latest/s//junk/" x | ex info.txt;
但问题是它在没有“ex”的图像中运行。
有没有办法与“awk”相关?我想我可以逐行读取文件并以这种方式执行某些操作,但我一直在寻找更简单的方法。如果是单行的话就没有问题了。我不能总是假设这是第一次出现或第二次出现。因此,我必须搜索包名称并仅替换该包的标签。
答案1
最简单的方法是使用命令行 YAML 解析器:
$ yq -y '.pkg1.image.tag |= "junk"' file
pkg1:
replicaCount: 1
image:
tag: junk
pullPolicy: Always
pkg2:
replicaCount: 2
image:
tag: latest
pullPolicy: Always
我在用着yq
,安德烈·基斯柳克jq
YAML 文档包装器(还有其他工具yq
也被调用,请确保您使用正确的工具)。
该命令将.pkg1.image.tag
键的值设置为 string junk
,并且该-y
选项用于生成 YAML 输出(而不是默认的 JSON)。
我相信yq
这是基于 Debian 的 Linux 发行版上的默认设置,您必须将 YAML 文档转换为 JSON,使用 进行修改jq
,然后将其转换回来:
$ yq r -j file.yml | jq '.pkg1.image.tag |= "junk"' | yq r -P -
pkg1:
replicaCount: 1
image:
tag: junk
pullPolicy: Always
pkg2:
replicaCount: 2
image:
tag: latest
pullPolicy: Always
答案2
如果perl
可用:
PKG=pkg1 FIELD=tag VALUE=junk perl -pi -e '
$pkg = $1 if /^(\S.*?)\s*:\s*$/;
s/^\s+\Q$ENV{FIELD}\E\s*:\s*\K.*/$ENV{VALUE}/ if $pkg eq $ENV{PKG}' -- "$file"
除了最新版本的 GNU 实现之外,awk
不支持就地编辑文件。如果您awk
实际上是最近的傻瓜,您可以执行与上述相同的操作:
PKG=pkg1 FIELD=tag VALUE=junk gawk -i /usr/share/awk/inplace.awk -e '
match($0, /^([^[:space:]](.*[^[:space:]])?)[[:space:]]*:[[:space:]]*$/, f) {
pkg = f[1] ""
}
pkg == ENVIRON["PKG"] {
$0 = gensub("^([[:space:]]+"ENVIRON["FIELD"]"[[:space:]]*:[[:space:]]*).*", \
"\\1" ENVIRON["VALUE"], 1)
}
{print}' -E /dev/null "$file"
我尝试解决APIawk
的一些限制和注意事项awk
:
-v var=value
使用mangles 反斜杠方法作为环境变量传递的参数pkg = f[i] ""
:附加 a""
以确保被视为字符串,pkg
以确保比较始终是字符串比较(awk
没有==
vs )eq
perl
-e 'code' -E /dev/null "$file"
(GNU 扩展)需要它才能处理任意文件名。
但还剩下一些,这意味着在某些输入的极端情况下它仍然无法正常工作:
- 没有相当于 / 的东西
perl
,\Q
因此如果包含 awk 正则表达式运算符(字符),\E
它将无法正常工作FIELD
.^${}[]\?+*|
VALUE
如果包含&
或字符在 的替换参数\
中被特殊处理,它将无法正常工作。gawk
gensub()
^不使用-i inplace
as尝试首先从当前工作目录gawk
加载inplace
扩展(asinplace
或),有人可能已经在其中植入了恶意软件。随系统提供的扩展inplace.awk
的路径可能会有所不同,请参阅输出inplace
gawk
gawk 'BEGIN{print ENVIRON["AWKPATH"]}'