使用 sed 替换使用多行文本范围的范围内的字符串

使用 sed 替换使用多行文本范围的范围内的字符串

我的文件(values.yaml)中有以下内容:

global:
  repo1:
    enabled: true
  repo2:
    enabled: true

repo1:
  replicaCount: 1
  image:
    tag: latest
    pullPolicy: Always

repo2:
  replicaCount: 1
  image:
    tag: latest
    pullPolicy: Always

我想tag: latest用类似的东西替换 for repo1 tag: newest1tag: latest用类似的东西替换 for repo2 ,tag: newest2这样我最终会得到:

global:
  repo1:
    enabled: true
  repo2:
    enabled: true

repo1:
  replicaCount: 1
  image:
    tag: newest1
    pullPolicy: Always

repo2:
  replicaCount: 1
  image:
    tag: newest2
    pullPolicy: Always

因此,我尝试搜索从文件repo1:\n replicaCount:1pullPolicy文件末尾的范围,这样我得到的范围中只有一个标签,并且可以替换它。

我有

sed -i "" "N;/repo1:\n  replicaCount:/,/pullPolicy/s/tag:.*/tag: newest1/g" values.yaml

然后几乎有效,但它总是删除最后pullPolicy一行,例如:

global:
  repo1:
    enabled: true
  repo2:
    enabled: true

repo1:
  replicaCount: 1
  image:
    tag: newest1
    pullPolicy: Always

repo2:
  replicaCount: 1
  image:
    tag: newest2

我使用的是 Mac,这就是为什么所有的双引号。

如何指定结束范围为文件末尾(我也尝试过$但无济于事)或为 pullPolicy?

答案1

sed -z使用空字符分隔符而不是换行符。

cat values.yaml | sed -z "s/\nrepo\([0-9]*\):\n\(\([^\n]\+\n\)*\)\([ \t]*\)tag:[^\n]*/\nrepo\1:\n\2\4tag: new\1/g"

做你想做的事。

  • \nrepo\([0-9]*\):\n匹配以 开头的行repo,并将其值记录在 中\1

  • \(\([^\n]\+\n\)*\)与任意数量的非空行(\+至少一个字符)匹配,并将其值记录在\2.\3对于内部群体来说是浪费了。

  • \([ \t]*\)tag:[^\n]*tag与包含带有空格缩进的单词的行匹配。

  • \nrepo\1:\n\2\4让第一行不变。

  • tag: new\1new使用+ repo 值更改标签值。

  • /g用于通过单个命令完成这两项更改。

如果它不起作用,您可以尝试使用gnu-sed(也可以安装在 MacOS 上)而不是默认的sed.

答案2

sed -ri ':1;/^repo[12]/,/tag/!b;/tag/!{N;b1};s/^(repo(.).*)latest$/\1newest\2/'

不要忘记用于调试的命令,它显示当前缓冲区中的内容。例如:

sed -nr ':1;/^repo[12]/,/tag/!b;/tag/!{N;b1};l;s/^(repo(.).*)latest$/\1newest\2/' file

repo1:\n  replicaCount: 1\n  image:\n    tag: latest$
repo2:\n  replicaCount: 1\n  image:\n    tag: latest$

生产:

sed -ri '/^repo[12]/!b;:1;/tag/!{N;b1};s/^(repo(.).*)latest$/\1newest\2/' file

答案3

使用python编辑此文件的方式是导入 yaml 模块,然后将 yaml 文件加载到 python 字典(又名 hash | )中。关联数组,尽管是嵌套数组。

然后我们调整 yaml 文件中键的值。

最后我们将字典保存回 yaml 文件中。

sed 代码是在 yaml 文件的顶级节点上插入空行。

$ yaml_file='values.yaml'

$ python3 - "$yaml_file" <<\YAML
import sys, yaml

yaml_doc = sys.argv[1]

with open(yaml_doc) as fp:
  h = yaml.safe_load(fp)

h['repo1']['image']['tag'] = 'newest1'
h['repo2']['image']['tag'] = 'newest2'

with open(yaml_doc, 'w') as fp:
  yaml.safe_dump(h, fp, default_flow_style=False)
YAML

$ sed -Ei -e '1!{/^\S/{H;z;x;};}' "$yaml_file" 

相关内容