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

おすすめ記事