Naveen Kumar
Naveen Kumar

Reputation: 2980

Linux shell get value of a field from a yml file

I have a database.yml file like

development:
  adapter: mysql2
  encoding: utf8
  database: d360
  host: localhost
  username: root
  password: password

test:
  adapter: mysql2
  encoding: utf8
  database: sample
  host: localhost
  username: root
  password: password

Now, I want value of database of test environment (that is sample for the YAML shown). How can we do that using sed?

Upvotes: 44

Views: 75542

Answers (5)

brian d foy
brian d foy

Reputation: 132778

There are better tools than sed. You might be stuck on a minimal system, but other people looking for an answer probably won't be.

The python version of yq acts like jq:

$ pip3 install yq
$ yq -r .test.database database.yml
sample

shyaml works too, but has an odd restriction that you can only redirect into it:

$ pip3 install shyaml
$ shyaml get-value test.database < database.yml
sample

If perl is around and you have YAML installed:

$ cpan YAML
$ perl -MYAML -le 'print YAML::LoadFile(shift)->{test}{database}' database.yml
sample

Or, if you want ruby:

$ ruby -r yaml -e 'puts YAML.load_file(ARGV[0])["test"]["database"]' database.yml
sample

Upvotes: 33

allap
allap

Reputation: 676

On Ubuntu, install yq:

$ sudo apt update
$ sudo apt install snapd
$ sudo snap install yq

Use yq:

$ value=$(yq r database.yml test.database)`

Upvotes: 14

Matt Dunn
Matt Dunn

Reputation: 5390

For macOS / Linux users using Homebrew, yq is available, and provides a jq-like expeience:

$ brew install yq
$ yq eval .test.database database.yml
sample

Upvotes: 3

ghoti
ghoti

Reputation: 46826

YAML obviously isn't natively supported in shell. But sed also isn't a YAML parser. Neither are grep, tail, cut, etc. I'm pretty sure you'd need an actual language in which to write a proper parser. Awk, perl, python, erlang, etc.

You could use sed or shell or somesuch if you know that your YAML data will always be formatted in a certain way or hold certain values in a particular order, but to make a parser that will work generally, and on any ol' YAML file you point it at, you'll need to emulate the parsers that already exist in other languages.

If you don't want to write your own (perhaps asking the StackOverflow community for help once you have some code to consider), then one option might be to install a tool like shyaml which can accurately parse files and give you authoritative content. A quick solution easily implemented into your scripts, though it has some dependencies (python).

Upvotes: 8

David C. Rankin
David C. Rankin

Reputation: 84531

That is fairly easy, not using sed, but with appropriate shell tools. First, if you need to preserve sample in a variable for later use, then something like the following will work using bash substring replacement to isolate sample on the Test:/database: line:

$ db=$(grep -A3 'test:' database.yml | tail -n1); db=${db//*database: /}; echo "$db"
sample

or for a shorter solution that you can dump to the command line, remove the variable and command substitution and use a tool like cut:

$ grep -A3 'test:' database.yml | tail -n1 | cut -c 13-
sample

or, with awk, simply:

$ grep -A3 'test:' database.yml | tail -n1 | awk '{ print $2}'
sample

All of the different ways can be used inside command substitution (i.e. var=$(stuff) ) to store sample in var, it is just a matter of which you would rather use. I think you get the idea.

Upvotes: 31

Related Questions