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私はrepo1をこのようなものに変更し、tag: newest1repo2tag: latestをこのようなものに変更したいと思います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

そのため、その範囲から1つのタグのみをインポートして置き換えることができるように、ファイルからファイルの終わりまでのrepo1:\n replicaCount:1範囲を検索してみます。pullPolicy

私は持っています

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\)*\)空でない行(\+少なくとも1文字以上)を一致させ、その値をに書き込みます\2\3内部コミュニティには無駄です。

  • \([ \t]*\)tag:[^\n]*tagスペースでインデントされた単語を含む行を見つけます。

  • \nrepo\1:\n\2\4最初の行は変更せずに残します。

  • tag: new\1newタグ値を変更するには、+ repo値を使用してください。

  • /g単一のコマンドで両方の変更を実行するために使用されます。

うまくいかない場合はgnu-sedデフォルト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辞書(ハッシュ|とも呼ばれる)にロードすることです。入れ子になった配列ですが、連想配列です。

次に、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" 

関連情報