views:

55

answers:

2

Hi all:

Here is a "challenge question" I've got from Linux system programming lecture.

Any of the following strings will give you a Coke if you kick:

L = { aaaa, aab, aba, baa, bb, aaaa"a", aaaa"b", aab"a", … ab"b"a, ba"b"a, ab"bbbbbb"a, ... }

The letters shown in wrapped double quotes indicate coins that would have fallen through (but those strings are still part of the language in this example). Exercise (a bit hard) show this is the language of a regular expression

And this is what I've got so far :

#!/usr/bin/bash
echo "A bottle of Coke costs you 40 cents"
echo -e "Please enter tokens (a = 10 cents, b = 20 cents) in a
sequence like 'abba' :\c"
read tokens

#if [ $tokens = aaaa ]||[ $tokens = aab ]||[ $tokens = bb ]
#then
#       echo "Good! now a coke is yours!"
#else    echo "Thanks for your money, byebye!"

if [[ $tokens =~ 'aaaa|aab|bb' ]]
then
        echo "Good! now a coke is yours!"
else    echo "Thanks for your money, byebye!"
fi

Sadly it doesn't work... always outputs "Thanks for your money, byebye!" I believe something is wrong with syntax... We didn't provided with any good reference book and the only instruction from the professor was to consult "anything you find useful online" and "research the problem yourself" :(

I know how could I do it in any programming language such as Java, but get it done with bash script + regex seems not "a bit hard" but in fact "too hard" for anyone with little knowledge on something advanced as "lookahead"(is this the terminology ?)

I don't know if there is a way to express the following concept in the language of regex:

Valid entry would consist of exactly one of the three components : aaaa, aab and bb, regardless of the order in a component, followed by an arbitrary sequence of a or b's

So this is what it should be like :

(a{4}Ua{2}bUb{2})(aUb)*

where the content in first braces is order irrelevant.

Thanks a lot in advance for any hints and/or tips :)

Oh, and forget about returning any money back to the user, they are all mine :)

Edit : now the code works ,thanks to Stephen has pointed out my careless typo.

+1  A: 

You have:

if [[ $token =~ 'aaaa|aab|bb' ]]

$token should be $tokens and remove the quotes from the regex.

if [[ $tokens =~ aaaa|aab|bb ]]

But, now you'll have to work on removing the quotes.

Stephen
@Stephen : shame on my careless typo...
Michael Mao
+1  A: 

you don't need a regular expression.

case $tokens in 
 aaaa|aab|bb) echo "coke!";;
 *) echo "no coke";;
esac

note the above checks for exactly "aaaa" or exactly "aab"..if you don't care how many characters after that, use wildcard

case $tokens in 
 aaaa*|aab*|bb*) echo "coke!";;
 *) echo "no coke";;
esac
ghostdog74
@ghostdog74 : firstly, thanks for showing me the case command. It works and I feel this is better than pipelining all the conditions in a if statement.However, this still would not lead to the correct output if user enters "baa". Obviously I can make up a complete case statement to catch all the cases that match 40 cents:) But I wonder if there is a way to use a "simple" regex to cover all?
Michael Mao
@ghostdog74 : just saw your edit...
Michael Mao