0k / shyaml

YAML for command line
BSD 2-Clause "Simplified" License
767 stars 57 forks source link

Values with multiples word are exploded #55

Closed opouy closed 3 years ago

opouy commented 4 years ago

YAML File :

---
    add_app:
        app_type:           'wordpress'
        app_name:           'demo'
        app_wp_plugins:
            - 'elementor'
            - 'Advanced Custom Fields'
        app_init_script:     'TRUE'
...

SCRIPT :

    for PLUGIN in `cat ${PROJECT_YML_PATH_FILE} | shyaml get-values add_app.app_wp_plugins`
    do
      echo  -e " Install -> '${PLUGIN}'"
    done 

CURRENT RESULT :

 Install -> 'elementor'
 Install -> 'Advanced'
 Install -> 'Custom'
 Install -> 'Fields'

EXPECTED RESULT :

 Install -> 'elementor'
 Install -> 'Advanced Custom Fields'

Is it a bug or a wrong usage ? thanks a lot for your help.

vaab commented 4 years ago

Hi, thanks for your report, I may be able to help you on that, indeed, this seems a wrong usage. Let me explain:

In your for instruction, bash will split the result of your command between back-ticks using spaces as separators (you might want to read about IFS variable in bash documentation). However, the output of your shyaml call will use spaces to separate values, but will also have spaces from one of your values. To avoid ending with this situation where bash can't solve this ambiguity, we can ask shyaml to use different separator character between values. This is documented in the README.rst about using NUL character to separate output from shyaml. NUL character is pretty much the best one to pick as you can't have them in a YAML value : we are sure to be compatible with any type of YAML content. The slight difficulty is to properly parse NUL-separated content with bash.

Here's your example:

Let's create a test.yml

cat <<EOF > /tmp/test.yml
add_app:
    app_type:           'wordpress'
    app_name:           'demo'
    app_wp_plugins:
        - 'elementor'
        - 'Advanced Custom Fields'
    app_init_script:     'TRUE'
EOF

I can proceed to show you an example of how to properly parse the values using NUL chars as value separator in shyaml's output, and avoiding the fairly common issue that you've encountered.

I like to use this convenience bash function, which will replace read builtin from bash to read NUL-separated data:

read-0() {
    local eof= IFS=''
    while [ "$1" ]; do
        read -r -d '' -- "$1" || eof=1
        shift
    done
    [ -z "$eof" ]
}

The parsing can then be done like this:

while read-0 PLUGIN; do
    echo -e " Install -> '${PLUGIN}'"
done < <(shyaml get-values-0 add_app.app_wp_plugins < /tmp/test.yml)

Which will output:

 Install -> 'elementor'
 Install -> 'Advanced Custom Fields'

If you need more info about NUL-separated fields and this read-0 function, I've written a few notes about that here: http://vaab.blog.kal.fr/2015/01/03/bash-lore-how-to-properly-parse-nul-separated-fields/

Note that this topic is already covered also in the README.rst provided as main documentation page and displayed on github. https://github.com/0k/shyaml

If you have any suggestion how to improve the documentation on this topic or if you feel my answer is not pertinent in any way, please feel free to tell it here and give me more details so I can help you more.