LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Bash question (https://www.linuxquestions.org/questions/programming-9/bash-question-943782/)

dth4h 05-07-2012 08:16 PM

Bash question
 
\/ FORGET THIS, read my second post \/

Code:

while [ $continue = no ];do
read -p "Some question" answer
if [ "$answer" != "1" -a "$answer" != "2" -a "$answer" != "3" -a "$answer" != "4" -a "$answer" != "5" -a "$answer" != "6" -a "$answer" != "y" -a "$answer" != "e" -a "$answer" != "remove" ];then
  echo "Option not recognised"
  continue=no
fi


The third line is the only one that is really relevant. What is a simpler way of writing the third line? Basically instead of it checking for all those numbers, I just want to make sure that it is a number, and that it isn't more then 99.
And for the other options, my Dad said he remembered that he used to do something like this:
if [ "$answer" != [y|e|remove] ];then
but he doesn't remember the exact syntax. And I tried that and it didn't work. So do any of you know the right way of doing that or something similar?

Tinkster 05-07-2012 09:21 PM

But you're accepting "e", "y", and "remove", so your text explanation
doesn't match your code ...

dth4h 05-07-2012 09:31 PM

Ok forget about everything else. I figured out how to do the number part. I just want to know if there is something similar to this that is right:
if [ "$answer" != [y|e|remove] ];then

This put in a sentence "If the answer is not y, e or remove then"

My long current way of doing this that I want to shorten (because if I have like 20 options then this line could get really long):
Code:

while [ $continue = no ];do
read -p "Some question" answer
if [ "$answer" != "y" -a "$answer" != "e" -a "$answer" != "remove" ];then
  echo "Option not recognised"
  continue=no
fi

NOTE: The options are not important, I just used them as examples.

jlinkels 05-07-2012 09:53 PM

This is maybe not very efficient, but it seems elegant:
Code:

correct_answer=0
for test_answer in y n remove spam eggs foo bar
do
  if [ $answer == $test_answer ]
  then
    correct_answer=1
  fi
done
if [ $correct_answer -ne 1 ]
then
  #do something
fi

Beware, this is not tested code, it might contain errors!

jlinkels

dth4h 05-07-2012 10:15 PM

Quote:

Originally Posted by jlinkels (Post 4672946)
This is maybe not very efficient, but it seems elegant:
Code:

correct_answer=0
for test_answer in y n remove spam eggs foo bar
do
  if [ $answer == $test_answer ]
  then
    correct_answer=1
  fi
done
if [ $correct_answer -ne 1 ]
then
  #do something
fi

Beware, this is not tested code, it might contain errors!

jlinkels

This works. I never knew there was "for" to use for loops. I thought there was only while. This is so cool. Thanks :)!

I am still curious though if there is a right way of doing what I posted. I know my Dad used to do something like it and I have seen it a few places on the internet before, but when I wanted to use it I could never find it again.

Anyway, thanks again jlinkels.

catkin 05-07-2012 11:05 PM

A case statement is more natural and easily allows accepting Y as equivalent to y etc:
Code:

case $answer in
    y | Y | e | E | remove )
        ;;
    * )
        <commands to be run when answer is invalid>
esac


dth4h 05-07-2012 11:15 PM

Quote:

Originally Posted by catkin (Post 4672987)
A case statement is more natural and easily allows accepting Y as equivalent to y etc:
Code:

case $answer in
    y | Y | e | E | remove )
        ;;
    * )
        <commands to be run when answer is invalid>
esac


Thanks catkin, that's even better!

Tinkster 05-07-2012 11:21 PM

And a third version ... ;D

Code:

regex="y|e|remove"
answer="y"
if [[ $answer =~ $regex ]]; then echo "Known"; fi
Known
answer="blub"
if [[ $answer =~ $regex ]]; then echo "Known"; fi


Cheers,
Tink

dth4h 05-07-2012 11:25 PM

Quote:

Originally Posted by Tinkster (Post 4672992)
And a third version ... ;D

Code:

regex="y|e|remove"
answer="y"
if [[ $answer =~ $regex ]]; then echo "Known"; fi
Known
answer="blub"
if [[ $answer =~ $regex ]]; then echo "Known"; fi


Cheers,
Tink

I think this is my most favorite thread ever! :D Thanks everyone!

Tinkster 05-08-2012 12:02 AM

Quote:

Originally Posted by dth4h (Post 4672997)
I think this is my most favorite thread ever! :D Thanks everyone!

In that case show the participants some love, and either click on the
little scales on the far left of their posts, or click the "helpful"
link within their posts ;}

dth4h 05-08-2012 12:15 AM

Quote:

Originally Posted by Tinkster (Post 4673012)
In that case show the participants some love, and either click on the
little scales on the far left of their posts, or click the "helpful"
link within their posts ;}

Oh, that's cool. I will do that.

One note though. A side effect of your solution is that you can enter a lot of other things that aren't in the variable "regex" and the answer will be accepted. I haven't quite been able to figure out the pattern yet but here are some examples:
re
reeeeeeeeeeeeee
er
yre

Tinkster 05-08-2012 12:18 AM

Quote:

Originally Posted by dth4h (Post 4673015)
Oh, that's cool. I will do that.

One note though. A side effect of your solution is that you can enter a lot of other things that aren't in the variable "regex" and the answer will be accepted. I haven't quite been able to figure out the pattern yet but here are some examples:
re
reeeeeeeeeeeeee
er
yre

Easy fix
Code:

regex='^y$|^e$|^remove$'
;0)

dth4h 05-08-2012 12:19 AM

Quote:

Originally Posted by Tinkster (Post 4673016)
Easy fix
Code:

regex='^y$|^e$|^remove$'
;0)

Ahhh, cool. Thanks

grail 05-08-2012 03:13 AM

Tink Tink Tink .... you must be getting slack in your old age ... lol .. just kidding:
Code:

regex='^(y|e|remove)$'
I would add that to remove the element of case surprise, I would add:
Code:

case ${answer,,} in

# or

if [[ ${answer,,} =~ $regex ]]

Also, you indicated that there are many options, so to help with creating the regex, I would suggest an array:
Code:

elements=(y e remove)

# or if stored in a file with one option per line
#elements=($(< file_with_options))

IFS="|"
regex="^(${elements[*]})$"
unset IFS

if [[ ${answer,,} =~ $regex ]]; then echo "it's here";fi

# or with the case statement
# IFS="|"
# case ${answer,,} in
#    "${elements[*]}") echo it has an element;;
#    *) echo it does not;;
# esac
# unset IFS


catkin 05-08-2012 06:41 AM

Nice, grail, nice :) Robust and elegant


All times are GMT -5. The time now is 06:33 PM.