Skip to content

Instantly share code, notes, and snippets.

@webghostx
Forked from masukomi/yaml_parser.md
Created December 20, 2024 08:30
Show Gist options
  • Select an option

  • Save webghostx/ddb5fca8148f78f5772e4c5ebe69f5f6 to your computer and use it in GitHub Desktop.

Select an option

Save webghostx/ddb5fca8148f78f5772e4c5ebe69f5f6 to your computer and use it in GitHub Desktop.

Revisions

  1. @masukomi masukomi created this gist Jun 4, 2015.
    97 changes: 97 additions & 0 deletions yaml_parser.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    Found [here](http://stackoverflow.com/questions/5014632/how-can-i-parse-a-yaml-file-from-a-linux-shell-script/21189044#21189044) by [Stephan Farestam](http://stackoverflow.com/users/1792684/stefan-farestam)

    Here is a bash-only YAML parser that leverages sed and awk to parse simple yaml files:

    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);
    }
    }'
    }

    It understands files such as:

    ## global definitions
    global:
    debug: yes
    verbose: no
    debugging:
    detailed: no
    header: "debugging started"

    ## output
    output:
    file: "yes"


    Which, when parsed using:

    parse_yaml sample.yml

    will output:

    global_debug="yes"
    global_verbose="no"
    global_debugging_detailed="no"
    global_debugging_header="debugging started"
    output_file="yes"

    it also understands yaml files, generated by ruby which may include ruby symbols, like:

    ---
    :global:
    :debug: 'yes'
    :verbose: 'no'
    :debugging:
    :detailed: 'no'
    :header: debugging started
    :output: 'yes'

    and will output the same as in the previous example.

    typical use within a script is:

    eval $(parse_yaml sample.yml)

    parse_yaml accepts a prefix argument so that imported settings all have a common prefix (which will reduce the risk of namespace collisions).

    parse_yaml sample.yml "CONF_"

    yields:

    CONF_global_debug="yes"
    CONF_global_verbose="no"
    CONF_global_debugging_detailed="no"
    CONF_global_debugging_header="debugging started"
    CONF_output_file="yes"

    Note that previous settings in a file can be referred to by later settings:

    ## global definitions
    global:
    debug: yes
    verbose: no
    debugging:
    detailed: no
    header: "debugging started"

    ## output
    output:
    debug: $global_debug

    Another nice usage is to first parse a defaults file and then the user settings, which works since the latter settings overrides the first ones:

    eval $(parse_yaml defaults.yml)
    eval $(parse_yaml project.yml)