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.

Usability testing of a shell script I wrote found that people had different expectations on how to answer a question that expected ‘yes’ as the answer. See variations in the below code example.

Surely there must be a better way that what I came up with? What is your readable and shorter form take on this?

read -p 'Answer this question with yes: ' answer
if [ "$answer" = 'Y'
  -o "$answer" = 'YES'
  -o "$answer" = 'Yes'
  -o "$answer" = 'y'
  -o "$answer" = 'yes'
  -o some-alternate-condition ]; then

  echo 'Surely this can be written better?'
fi
share|improve this question
2  
Voted to close. While I'm interested in the question, it's probably more of a programming question, so should be on SO. –  phunehehe May 22 '11 at 15:50
    
A programming answer might be something like Bash: Check if array element exists –  phunehehe May 22 '11 at 15:57
3  
@phunehehe: I disagree with moving to SO, not only because we have a history of accepting shell programming, but also because it's not just a question of how to do it but also a question of what the spec should be. –  Gilles May 22 '11 at 16:00
4  
I wrote a script much like that once. Then the program was translated to French and Simplified Chinese. I skimmed the French version and saw my prompt was translated to "Enter oui or non" but of course the code still wanted "Y*" or "N*" –  Ben Jackson May 22 '11 at 21:38
add comment

5 Answers

up vote 16 down vote accepted

Using a case is somewhat equivalent but not perfect since statements like YE are accepted.

read -p 'Answer this question with yes: ' answer
case "${answer}" in
    [yY]|[yY][eE][sS])
        echo 'Surely this can be written better?' ;;
esac
share|improve this answer
2  
I would say the user’s intent is pretty clear from ‘ye’. –  Aeyoun May 22 '11 at 18:29
add comment

Staying in bash (or any other shell if you display the prompt independently):

case $answer in
  [Yy]*) echo Ok;;
  *) echo "Can't you read? I said to say yes.";;
esac

This accepts responses like yn as yes,  y (with an initial space) as no, and wlkjzuhfod as no, which may not be optimal but is consistent with typical shell prompts: that's how rm -i, find -ok and others do it.

This eschews the whole issue of internationalization: in other languages, you would need to translate expected responses. There's no standard shell method then; you can turn to dialog, but then your script will require it to be installed (it's available in many distributions but not always installed by default).

if dialog --yesno "Choose yes" 0 0; then …
share|improve this answer
add comment

The UNIX standard provides example code for this using the locale utility:

if printf "%s\n" "$response" | grep -Eq "$(locale yesexpr)"
then
    affirmative processing goes here
else
    non-affirmative processing goes here
fi

The value for 'yesexpr' in the POSIX locale (and on English locales on real systems) is "^[yY]". It is to be interpreted as an extended regular expression. See also noexpr.

share|improve this answer
1  
Nice. But I seem to be an idiot. Where can I find a list of the arguments that locale knows about? The man page on my Mac OS 10.5 box doesn't seem to have them. –  dmckee May 22 '11 at 20:48
    
Nice. Could you please link back to the source? –  Aeyoun May 22 '11 at 21:51
3  
@dmckee you can do locale -k LC_MESSAGES (and for the other LC_whatever), or see here for ones defined by the standard. @Daniel what source other than the locale utility page that I did link? –  Random832 May 22 '11 at 22:20
1  
Great answer, should definitely be the accepted one. –  jlliagre Sep 16 '13 at 11:52
add comment

I usually use a simple function:

Confirm() { read -sn 1 -p "$* [Y/N]? "; [[ ${REPLY:0:1} = [Yy] ]]; }

The function just returns 0 if Y or y is entered and 1 if anything else is entered. It can be used with if...fi:

if Confirm "Type y or n"; then
echo "You typed y"
else
echo "You typed n"
fi

Or just like this:

Confirm "Type y" && echo "You typed y"
share|improve this answer
add comment

Just re-modified @faif ans

YesOrNo() {
        while :
        do
                read -p 'Do you want to Continue (yes/no?): ' answer
                case "${answer}" in
                    [yY]|[yY][eE][sS]) exit 0 ;;
                        [nN]|[nN][oO]) exit 1 ;;
                esac
        done
}


if $( YesOrNo ); then
        echo "Ans is yes.. Do something....."
else
        echo "Ans is No... skip.."
fi

Test

root@ubuntu:~# bash confirm.sh
Do you want to Continue (yes/no?):  # if Blank Enter then ask again
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?): no
Ans is No... skip..
root@ubuntu:~# bash confirm.sh
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?): ye
Do you want to Continue (yes/no?): yes
Ans is yes.. Do something.....
share|improve this answer
add comment

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.