文字列を見つけて最初の文字列を見つけ、次の行の別の文字列に置き換えます。

文字列を見つけて最初の文字列を見つけ、次の行の別の文字列に置き換えます。

以下の内容を含むファイルが提供されます。

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

pkg2:
  replicaCount: 2
  image:
    tag: latest
    pullPolicy: Always

tag特定のパッケージ(例:)に追加されたコンテンツを検索して別のパッケージ(例:)にpkg1置き換えると、次のような結果が得られます。latestjunk

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行ずつ読み、そのような方法でいくつかの作業を実行できると思いますが、より簡単な方法を探していました。一行であれば問題ありません。これが最初のものか2番目のものかを常に想定することはできません。そのため、パッケージ名を検索してそのパッケージのタグを置き換えるだけです。

答え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

私はそれを使用していますyqAndrei Kislyuk jqYAMLドキュメントラッパー(他のツールyqも呼び出されますので、正しいツールを使用していることを確認してください。)

このコマンドは.pkg1.image.tagキー値をstringに設定しjunk、この-yオプションはデフォルトのJSONの代わりにYAML出力を生成するために使用されます。

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"

awk私はAPIのいくつかの制限と注意事項を解決しようとしますawk

  • -v var=valueマングルバックスラッシュメソッドを使用してパラメータを環境変数に渡します。
  • pkg = f[i] "":比較が常に文字列比較であることを確認するために""文字列として処理されるようにaを追加します(いいえ対)。pkgawk==eqperl
  • -e 'code' -E /dev/null "$file"(GNU拡張)任意のファイル名を処理するために必要です。

しかし、いくつかの残りの部分があります。これは、特定の入力に対して特別なケースではまだ機能しないことを意味します。

  • perl/ と同等のものがないので、\Qawk 正規表現演算子 (char) を含めると\E動作しません。FIELD.^${}[]\?+*|
  • VALUE代替パラメータまたはインクルード&文字が特別に処理されると、\正しく機能しません。gawkgensub()

^使用しないでください-i inplace現在の作業ディレクトリから最初に拡張機能をgawkロードしようとすると、誰かがそのディレクトリにマルウェアを植えた可能性があります。システムに付属の拡張プログラムのパスは異なる場合があります。出力を参照してください。inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

関連情報