Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I have a shell script script.sh like this:

names=( jack john jerry)

And I want the user to type any of these three names as its first parameter, just like:

./script.sh jack

If the user typed a wrong one, for example

./script.sh kate

It will trigger a exit and ask the user to only type one from those 3.

What should I do?

share|improve this question

3 Answers 3

names=(jack john jerry); 
if [[ " "${names[@]}" " == *" "$1" "* ]] ;then 
    echo "$1: ok"
else 
    echo "$1: not recognized. Valid names are:"
    echo "${names[@]/%/,}"
    exit 1
fi

The above code works for names which do not contain whitespace.
The modified version, below, can handle whitespace in names.

names=("flash jack" john jerry); 
d=$'\1'   # validation delimiter - value is \x01
valid="${names[@]/%/$d}"
valid="$d${valid//$d /$d}"
if [[ $valid == *$d$1$d* ]] ;then 
    echo "$1: ok"
else 
    echo "$1: not recognized. Valid names are:"
    echo "${names[@]/%/,}"
    exit 1
fi

Output for whitespace aware version:

flash jack: ok

or

kate: not recognized. Valid names are:
flash jack, john, jerry,
share|improve this answer
    
Note: this can result in false positives if your input or list of names contains spaces –  Chris Down 15 hours ago
    
That's true Chris... but I intentionally answered as per the input data provided... Have now added whitespace capable version. –  Peter.O 14 hours ago

That's precisely what case statements are for:

#! /bin/bash

case $1 in
    [Jj]ack)
        echo "You chose Jack!"
    ;;
    [Jj]ohn)
        echo "You chose John!"
    ;;
    [Jj]erry)
        echo "You chose Jerry!"
    ;;
    ## For all other cases
    *)
        echo 'Please choose one of "John", "Jack" or "Jerry"' >&2
    exit 1
esac

The case statement will be run on the value of $1, the first parameter you pass to your script. If it is either jackor Jack, the first choice will be run, if it's John or john the second etc. If anything else is entered, the last statement will be run.

share|improve this answer

Firstly, I need to mention that shell scripts substantial enough to use the horrid array implementation are probably going to be regarded as the spawn of the devil. Also, you didn't indicate what shell, but I am assuming bash.

There are many ways to do this, all ugly.

1) Iterate over the array. It's readable and relatively clean, but inefficient.

for i in 0 1 2 3 4
do
echo compare ${ARRAY[$i]} perhaps using test or whatever you like
done

2) Use expr to do it all at once. This is fragile and will break if one name is a substring of another. That can be fixed, but I would recommend using a better tool if it comes to that

$ ARRAY=(jack john jerry )
$ expr "${ARRAY[*]}" : '.*jack.*'
15  # it's found
$ expr "${ARRAY[*]}" : '.*sue.*'
0   # not found

Where jack or sue are replaced by $1 or whatever arg you want to check.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.