Martin Broder
Martin Broder

Reputation: 335

zsh - read user input with default value - empty input not empty?

I wrote a function that asks for user input like this:

function is_confirmed {

    read -rs -k 1 ans

    if [[ "${ans}" == "n" || "${ans}" == "N" ]]; then
        printf "No\n"
        return 1
    fi

    if [[ "${ans}" == "y" || "${ans}" == "Y" ]]; then
        printf "Yes\n"
        return 0
    fi

    # here is my actual problem!!! this doesnt work when user input is blank!
    if [[ "${ans}" == "" ]]; then
        printf "Yes!\n"
        return 1
    fi

    # Output is Damn!
    printf "Damn"
    return 1
}

works great so far, however, I want to set "yes" as the default answear, so when the user inputs nothing and just presses enter, it should fall back to "yes", so I tried it with || "$ans" == "" but that still falls back to "Damn"

how come? When I echo $ans at the end of the function it is empty...

EDIT 1:

This is what happens:

e_ask "Are you sure you want to install?\nWarning: This may override some files in your home directory."

if is_confirmed; then
    echo "Great!"
else
    e_error "Aborting..."
fi

here are the functions:

function e_ask {
    printf "\n$1\n"
    printf "(Y/n): "
}

function e_warn {
    printf "Warning: $1\n"
}

function e_error {
    printf "Error: $1\n"
    exit 1
}

Upvotes: 3

Views: 5764

Answers (3)

sauletasmiestas
sauletasmiestas

Reputation: 438

Just add default variable in the beginning of function:

function is_confirmed {

    ans="y"

    echo "Put your choice:"
    read $ans


}

If nothing is typed in, default value will remain.

Upvotes: 3

giordano
giordano

Reputation: 8344

A case is better when you want to consider many different values and a default one

function is_confirmed {

    read -rs -k 1 ans

    case "${ans}" in
    y|Y|$'\n')
        printf "Yes\n"
            return 0
        ;;

    *)  # This is the default
        printf "No\n"
            return 1

    esac

}

Upvotes: 3

Samveen
Samveen

Reputation: 3540

The problem lies in how you wrote your conditions using the [[ builtin.

You need to change your conditions to:

function is_confirmed {

    read -rs -k 1 ans

    if [[ "${ans}" == "n" ]] || [[ "${ans}" == "N" ]]; then
        printf "No\n"
        return 1
    else if [[ "${ans}" == "y" ]] || [[ "${ans}" == "Y" ]]; then
        printf "Yes\n"
        return 0
    else if [[ -z "${ans}" ]]; then
        printf "Empty\n"
    else
        printf "Damn\n"
    fi

    return 1
}

To explain, the [[ builtin tests just one condition, but you can chain multiple instances of [[ with && and ||. Your code, in contrast, tried to test 2 conditions inside [[ and used || as it's C/C++ usage.

More details available in help [[ or man bash

Upvotes: 1

Related Questions