sedを使用して複数行を置き換える

sedを使用して複数行を置き換える

YAMLファイルの次のセクションを置き換えようとしています。

  ssl:
    enabled: false

読む

  ssl:
    enabled: true

私はこれを試しましたが失敗しました。sed -i s/ssl:\n enabled: false/ssl:\n enabled: true/g

答え1

範囲を使用できますsed

sed '/^ *ssl:/,/^ *[^:]*:/s/enabled: false/enabled: true/' file

範囲の境界は/^ *ssl:/(ssl セクションの先頭) と/^ *[^:]*:/(その他のセクション) です。

これはs一般的な置換コマンドです。

答え2

YAMLをサポートするツールを使用してください。たとえば、Perlでは次のことができます。

perl -MYAML=LoadFile,DumpFile -we '
    $y = LoadFile("file");
    $y->{ssl}{enabled} = "true" if $y->{ssl}{enabled} eq "false";
    DumpFile("file.new", $y);'

答え3

申し訳ありません。 @chorobaのコメントに同意し、yamlを解析して作成するためのツールを使用してください。 sed 構文解析は正しい方法ではありません。複数の連続した末尾行と異なるインデントがある場合があります。正規表現は複雑すぎる可能性があり、最終的に独自のYamlパーサーを作成します。

Bashシェルで利用可能なRubyソリューションは次のとおりです。

echo "ssl:
enabled: false
" | bundle exec ruby -e "require 'psych';
 c = Psych.load(STDIN.read); c['ssl']['enabled'] = true;
 puts c.to_yaml" > updated_dest.yml

2つの引数を持つシェルスクリプトが必要な場合でも簡単です。

#!/usr/bin/env ruby

require 'psych'
c = Psych.load_file(ARGV.shift)
c['ssl']['enabled'] = true
File.open(ARGV.shift, 'wb+') {|f| f.write(c.to_yaml)}

関連情報