Read YAML input file in BASH, C/C++ and Python

Utpal Kumar   2 minute read      

We will see how to read a YAML file in Bash, C/C++ and Python.

YAML is a data input format designed for easy readability and machine parsing. Although structured similar as JSON and XML, YAML is more verbose. In this post, we will see how to read a YAML file in Bash, C/C++ and Python.

Create a simple YAML file

Let us first create a simple YAML file to read later using the Bash, C and Python scripts, and save it as people.yml.

name: "Andrew" 
age: 22 
gender: "M"
country: "USA"

Using Bash

Now, let us read people.yml using Bash script. This script was obtained from the github gist of pkuczynski (see references).


function parse_yaml {
   local prefix=$2
   local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
   sed -ne "s|^\($s\):|\1|" \
        -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \
        -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p"  $1 |
   awk -F$fs '{
      indent = length($1)/2;
      vname[indent] = $2;
      for (i in vname) {if (i > indent) {delete vname[i]}}
      if (length($3) > 0) {
         vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
         printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3);
      }
   }'
}


eval $(parse_yaml people.yml)
echo $name
echo $country

For each key, value pair in the yaml file, this script will read the yaml key as a bash variable and assign its value to this variable.

Using C/C++

It is slightly more tricky to read YAML in C/C++. The two most detailed blog article I found for reading YAML files in C are listed in references. I recommend interested readers to go though those articles.

#include <stdio.h>
#include <yaml.h>
#include <assert.h>

int main()
{
    FILE *file;
    yaml_parser_t parser;
    yaml_document_t document;
    yaml_node_t *node;
    int i = 1;

    file = fopen("people.yml", "rb");
    assert(file);

    assert(yaml_parser_initialize(&parser));

    yaml_parser_set_input_file(&parser, file);

    if (!yaml_parser_load(&parser, &document)) {
        goto done;
    }

    // iterate through each node
    while(1) {
        node = yaml_document_get_node(&document, i);
        if(!node) break;
        if(node->type == YAML_SCALAR_NODE) {
            if (node->data.scalar.style == 1){ //assuming that the key is a string
                printf("%s: ", node->data.scalar.value);
                i++; 
                node = yaml_document_get_node(&document, i); //assuming that the value is stored as the next node
                if(!node) break;
                printf("%s (%d)\n", node->data.scalar.value, node->data.scalar.style); //value for each key and the type of value in the braces
            }
        }
        i++;
    }
    yaml_document_delete(&document);


    done:
      yaml_parser_delete(&parser); //to free memory
      assert(!fclose(file));

    return 0;
}

This script uses the libyaml library for YAML parsing and emitting. The above code is an example for parsing the YAML file. The parser takes an input stream of bytes and produces a sequence of events. We segregate the interested events based on the “data style”.

To compile and run the script:

>> gcc -lyaml read_yaml.c -o read_yaml
>> ./read_yaml
name: Andrew (3)
age: 22 (1)
gender: M (3)
country: USA (3)

Using Python

The reading of YAML files works flawlessly in Python. We can use the PyYAML library to parse YAML files.

import yaml

def read_yml(ymlfile):
    with open(ymlfile) as file:
        out_dict = yaml.load(file, Loader=yaml.FullLoader)
    return out_dict
people_dict = read_yml(ymlfile="people.yml")
print(people_dict)
>> python read_yml.py
{'name': 'Andrew', 'age': 22, 'gender': 'M', 'country': 'USA'}

References

  1. pkuczynski/parse_yaml.sh
  2. YAML files
  3. YAML documents parsing with libyaml in C

Disclaimer of liability

The information provided by the Earth Inversion is made available for educational purposes only.

Whilst we endeavor to keep the information up-to-date and correct. Earth Inversion makes no representations or warranties of any kind, express or implied about the completeness, accuracy, reliability, suitability or availability with respect to the website or the information, products, services or related graphics content on the website for any purpose.

UNDER NO CIRCUMSTANCE SHALL WE HAVE ANY LIABILITY TO YOU FOR ANY LOSS OR DAMAGE OF ANY KIND INCURRED AS A RESULT OF THE USE OF THE SITE OR RELIANCE ON ANY INFORMATION PROVIDED ON THE SITE. ANY RELIANCE YOU PLACED ON SUCH MATERIAL IS THEREFORE STRICTLY AT YOUR OWN RISK.


Leave a comment