Bash – Get specific result from function

bashechoexit-statusfunction

Is there a way to return a specific value in an echoing function?

return allows me to return an exit status for the function. I need to return a more sophisticated data structure such as an array, or a string. Usually I would need to echo the value I want to be returned. But what if I need to echo informative messages in my function, and I only need to get the last echo which holds the result I need?

I have this chunk of code I would like to make a function out of it, but I would like to keep the informative echo as they are useful for guiding the user's input.

modules=(module1 module2 module3)
is_valid=-1
while [ $is_valid -lt 1 ] 
do
    echo "Please chose and order the available modules you need:"
    echo -e $(list_array_choices modules[@])
    echo -n "> "
    read usr_input
    choices=("$usr_input")
    is_valid=$(is_list_in_range choices[@] ${#modules[@]})
    [ "$is_valid" -eq -1 ] && echo -e "Error: your input is invalid.\n"
done

I would like to do something like

function get_usr_choices() {
    modules=${!1}
    is_valid=-1
    while [ $is_valid -lt 1 ] 
    do
        echo "Please chose and order the available modules you need:"
        echo -e $(list_array_choices modules[@])
        echo -n "> "
        read usr_input
        choices=("$usr_input")
        is_valid=$(is_list_in_range choices[@] ${#modules[@]})
        [ "$is_valid" -eq -1 ] && echo -e "Error: your input is invalid.\n"
    done
    echo ${choices[@]}  # This is the result I need.
}
choices=$(get_usr_choices modules[@])

Alas the echos completely mess up the output as I get a string containing all the echo, including the informative ones. Is there a way to do what I want a clean way?

Best Answer

You could output all the other content directly to screen assuming you don't ever want to do anything with it other than display.

Something similar to this could be done

#!/bin/bash

function get_usr_choices() {
        #put everything you only want sending to screen in this block
        {
                echo these
                echo will
                echo go
                echo to
                echo screen
        }> /dev/tty
        #Everything after the block is sent to stdout which will be picked up by the assignment below
        echo result
}
choices=$(get_usr_choices)

echo "<choices is $choices>"

Running this returns

these
will
go
to
screen
<choices is result>
Related Question