1

Bash 4 on Linux ~
I have an array of possible values. I must restrict user input to these values.

Arr=(hello kitty goodbye quick fox)

User supplies value as argument to script:

bash myscript.sh -b var

Currently, I'm trying the following:

function func_exists () {
_var="$1"
for i in ${Arr[@]}
do
    if [ "$i" == "$_var" ]
    then
        echo hooray for "$_var"
        return 1
    fi
done
    return 0
}

func_exists $var
if [ $? -ne 1 ];then
    echo "Not a permitted value."
    func_help
    exit $E_OPTERROR
fi

Seems to work fine, are there better methods for testing user input against an array of allowed values?

UPDATE: I like John K's answer ...can someone clarify the use of $@? I understand that this represents all positional parameters -- so we shift the first param off the stack and $@ now represents all remaining params, those being the passed array ...is that correct? I hate blindly using code without understanding ...even if it works!

3 Answers 3

1

Your solution is what I'd do. Maybe using a few more shell-isms, such as returning 0 for success and non-0 for failure like UNIX commands do in general.

# Tests if $1 is in the array ($2 $3 $4 ...).
is_in() {
    value=$1
    shift

    for i in "$@"; do
        [[ $i == $value ]] && return 0
    done

    return 1
}

if ! is_in "$var" "${Arr[@]}"; then
    echo "Not a permitted value." >&2
    func_help
    exit $E_OPTERROR
fi

Careful use of double quotes makes sure this will work even if the individual array entries contain spaces, which is allowed. This is a two element array: list=('hello world' 'foo bar').

Sign up to request clarification or add additional context in comments.

2 Comments

Nice improvements! Thanks! Barring further brilliance this will get my vote.
My understanding of the $@ in your function: shift the first arg off the stack - $@ now represents the remainder. Is this correct?
1

Another solution. is_in is just a variable:

Arr=(hello kitty goodbye quick fox)

var='quick'

string=" ${Arr[*]} "                            # array to string, framed with blanks
is_in=1                                         # false
# try to delete the variable inside the string; true if length differ 
[ "$string" != "${string/ ${var} /}" ] && is_in=0

echo -e "$is_in"

1 Comment

Great solution. Thanks! I'll keep this one for later.
1
function func_exists () {
  case "$1"
  in
    hello)
    kitty)
    goodbye) 
    quick)
    fox)
      return 1;;
    *)
      return 0;;
  esac
}

5 Comments

To the down-voter: sorry, you saw my answer at the moment I accidentally submitted it due to hitting the wrong key. :)
This is a nice solution but I am not sure how readable it would be if the allowable input array contained 50 - 100 members.
Could also write it compactly in one case as hello|kitty|goodbye|quick|fox).
Am thinking for versatility and readability, an array or an array pulled from a file would be appropriate. Not sure the most efficient way to test input against such an array. The solution should be able to deal efficiently and readably against arrays with 50 plus members.
Another advantage to a separately defined array is that you could pass the array with the variable to test and have a reusable function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.