I'm trying to replace the following section of a YAML file:

    enabled: false

to read

    enabled: true

I've tried this, which failed: sed -i s/ssl:\n enabled: false/ssl:\n enabled: true/g


You can use sed ranges:

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

The range boundaries are /^ *ssl:/ (start of the ssl section) and /^ *[^:]*:/ (any other section).

The s is the usual substitution command.


Use a YAML-aware tool. For example, in Perl, you can

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

You were just close to find and you were only need to add -z option, also you can make it short as following.

sed -Ez 's/(ssl:\n\s*enabled: )false/\1true/g' infile

Sorry, but I will agree with @choroba and tell you to use a tool able to parse and write yaml. Sed parsing is not the right way. you might have different indentation, several continuous endlines. The regexp would get overly complicated and you would end up writing your own Yaml parser.

Here is a solution in ruby That you can use in Bash shell

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

if you want a shell script that takes two params, its also easy

#!/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)}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.