3

I'm in a situation very similar to the person in this post. I'm trying to write a script that populates values in the database.yaml file. Problem is...I totally don't understand what's going on in that regex that was posted as the solution.

What I want to do is pass in variables for the password.

If I have a database yml file that looks like this:

development:
  database: sample_development
  password:
  # etc...

test:
  database: sample_test
  password:
  # etc...

then how do create a regex that finds ' password: ' so I can replace it with ' password: $new_password' ?

For the part of the script that sets the development password, then I'm guessing the regex would begin

/^development:

But I'm at a loss from how to grab the next line down, ' password: '.

Any idea how I could do this?

Community
  • 1
  • 1
Ben Downey
  • 2,575
  • 4
  • 37
  • 57

3 Answers3

3

I would just use YAML library to read/write yaml files:

require 'yaml'
database_config = YAML.load(File.open("<some path>/config/database.yml"))

Then modify some values and write it back to fs:

database_config['some_key'] = "some_value"
File.open("<some path>/config/database.yml", "w") {|f| f.write(database_config.to_yaml) }

You can create a ruby script that will accept params to set passwords, host names etc. In addition to this, you can just use ruby inside of your YAML file to make it dynamic, yaml itself can read config files or environment variables and use them to set passwords, host names etc.

host: <%= SERVER_CONFIG["dev_host"] %>
iouri
  • 2,919
  • 1
  • 14
  • 11
2

You could use a sed script:

#!/bin/sed -f

: restart
/^development/ {
    : loop
    s/\(password:\).*/\1 new_password/
    t stop
    n
    /^[ \t]/ b loop
    i\  password: new_password
    b restart
} 
: stop

Here we have a sed script that will start the main block of commands when it finds a line that starts with "development". Before I explain what the commands do, I think it is a good idea to explain the labels. Labels are defined with the : command, and they give name to certain locations in the script. We define 3 labels.

  1. restart is used to go back to the start of the script.
  2. loop is used to iterate through the lines inside a development block.
  3. stop is used when we have performed the change to the password, and we go to the end of the script, which actually allows the script to restart on the next input line.

Inside the main block, we first try to apply the password change using an s substitute command. If it works, the t test command that follows performs a jump to the end of the script, allowing the execution to continue in case another development block is found.

If the substitute command doesn't succeed, the t command does nothing, and we continue with the n next command. This commands loads the next input line into the patter space (ie. sed's working buffer). We then check to see if it starts with a space or a tab, and if it does we jump to the "loop" label, allowing us to see if this new line is a line that contains the password field.

If it doesn't start with a white space character, we've reached the end of the block. The i insert command is optional, but with it we can add the password line at the end of the block when it isn't found.

Finally, since we reached the end of the block, we must restart execution. We could just let execution read the end of the script, but since we've loaded a new line that doesn't start with a white space character, we must manually jump to the start to prevent sed from loading another line before restarting.

You can then run this script (suppose it's called chg_passwd.sed) with:

./chg_passwd.sed database.yml

Hope this helps =)

  • Very cool. I've only seed sed scripts that specify the file name. How would I specify the filename in your example? – Ben Downey Oct 07 '12 at 21:05
  • 1
    Hi, I edited the script to fix the `-f` flag (which tells sed to execute the commands in the file), and added a command to insert the password line if it isn't found. I then added an explanation of the commands. Hopefully it's a little clearer =) – Janito Vaqueiro Ferreira Filho Oct 07 '12 at 22:21
1

This might work for you:

database=foo newpassword=bar
sed '/^'"${database}"'/,/^\s*$/s/password:/&'"${newpassword}"'/' file
potong
  • 55,640
  • 6
  • 51
  • 83