Help with if-else construct


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Help with if-else construct
# 8  
Old 11-02-2010
Honestly i am very grateful for your reply and its really getting clearer but i need some help with
this 'sed' statement. I was thinking that putting the questions in a separate 'questions' file and also redirecting the answers to a separate file 'answers' will make the script more robust and secure. Then i can call various lines of the questions individually. eg if i have this question in a separate file

3. What is the capital of the United States of America?
a) Florida
b) Chicago
c) Washington D.C
d) none of these
Enter answer

i can say "sed -n '1,5' ~/home/testing/questions
read answer
$answer > /home/testing/answers
to call the question. Another issue will be how i will compare this supplied answers
with the file 'right answers' containing the right answers and then display to the student
from the 'display' script file because the student should be able to access this display script
like say one week later to see his result again. Please can you help me with this?

Thanks so much.
# 9  
Old 11-03-2010
This should be most of the way there, just missing
- password/user validation
- view mode/stop re-answering

Currently set for 120 secs instead of 1 hour - so I could test the timeout situation.
Just set ALLOW_TIME to 3600 at the top of the script for 1 hour.

Data files:
Code:
$ cat questions
'What is the capital of the United States of America?
  a) Florida
  b) Chicago
  c) Washington D.C
  d) none of these'
'The sky is what colour?
  a) Blue
  b) Green
  c) Grey
  d) Orange'
'Insects have how many legs?
  a) 3
  b) 6
  c) 9
  d) 12'
'Which is the only fruit with the seeds on the outside?
  a) strawberry
  b) bananna
  c) orange
  d) lime'
 
$ cat correct
"c" "a" "b" "a"

Code:
Code:
#!/bin/bash
ALLOW_TIME=120
eval "QUESTIONS=($(cat questions))"
eval "CORRECT=($(cat correct))"
eval "ANSWER=($(cat answers))"
PRE="$( tput sc ; tput civis ; tput cup 0 60)"
POST="$( tput el ; tput rc ; tput cnorm)"
BACK="$( tput cub1 )"
do_timer()
{
   sleep 10
   WAIT=$1
   while [ -d /proc/$WAIT ]
   do
      if [ $SECONDS -gt $ALLOW_TIME ]
      then
         kill -14 $WAIT
         break;
      fi
      show_time
      [ $(($ALLOW_TIME-$SECONDS)) -gt 90 ] && sleep 20
      sleep 2
   done
}
show_time()
{
  LEFT=$(($ALLOW_TIME-$SECONDS))
  if [ $LEFT -lt 90 ]
  then
      echo -e "${PRE}Time to go: $LEFT secs${POST}\c"
  else
      echo -e "${PRE}Time to go: $((($LEFT+59)/ 60)) mins${POST}\c"
  fi
}
timeout()
{
   echo -e "\nTime is up...Sorry"
   save_answers
}
 
ask()
{
    clear
    echo "Question $((QNUM+1)) of ${#QUESTIONS[@]}"
    show_time
    echo
    echo -e "${QUESTIONS[$QNUM]}\n"
    echo -e "Your answer: ${ANSWER[$QNUM]:- }$BACK\c"
    read new_ans
    new_ans=${new_ans:-${ANSWER[$QNUM]}}
    case $new_ans in
        a|b|c|d) ANSWER[$QNUM]=$new_ans ;;
        *) echo "Illegal answer - please try again" ;
           sleep 1 ;
           return 2 ;;
    esac
    while true
    do
        echo -e "Type n for next, p for previous, q for quit: \c"
        show_time
        read nav
        case $nav in
            n|N) return 0 ;;
            p|P) return 1 ;;
            q|Q) return 3 ;;
        esac
    done
}
trap "timeout ; exit" 14
save_answers()
{
    echo -e "\c" > answers
    QNUM=0
    SCORE=0
    while [ $QNUM -lt ${#QUESTIONS[@]} ]
    do
        echo "\"${ANSWER[$QNUM]}\" " >> answers
        [ "${CORRECT[$QNUM]}" = "${ANSWER[$QNUM]}" ] && let SCORE=SCORE+1
        let QNUM=QNUM+1
    done
    echo "You got $SCORE questions correct out of ${#QUESTIONS[@]}"
}
do_timer $$ &
QNUM=0
while true
do
   ask $QNUM
   case $? in
       0)  let QNUM=QNUM+1 ;;  # Next
       1)  let QNUM=QNUM-1 ;;  # Prev
       3)  break ;; # Quit/Done
   esac
   [ $QNUM -ge ${#QUESTIONS[@]} ] && QNUM=0
   [ $QNUM -lt 0 ] && let QNUM=${#QUESTIONS[@]}-1
done
save_answers


Last edited by Chubler_XL; 11-03-2010 at 12:29 AM.. Reason: Tidyup formatting
# 10  
Old 11-03-2010
Thanks Chubler XL. You don't know how grateful i am. I am actually new to unix and i want to become a professional like you (in Unix administration) so i can excel in DBA role which i just passes the exams recently. I will try it out now cos i just saw the mail. Thanks so much again for being there for me.

---------- Post updated at 08:22 PM ---------- Previous update was at 11:16 AM ----------

Chubler_XL,

Wow you are really too much, as in, the best! I have spent the whole day on this
script and it works perfectly well! I have some work to now study each line and know
their meaning cos i have no met most of the commands like "eval", "tput", "post", "pre"
and so many others. I have succeeded in wrapping the script into my for-else loop, to make it accessible only to the right students. But please one more thing.
Please can you help me with a separate 'result' script. The result script is supposed to display the answers the student entered from 'answers' file in numeric order and compare with the the ones in the 'correct' file and compute the student's result e.g if i have eight questions and eight correct answers in the 'correct' file. The student logs in with user name and password the results are shown thus:

$ cat result
Your answers
1.) a
2.) b
3) d
4.) c
5.) a
6.) c
7.) c
8.) b

You got 5 correct out of 8
You Passed!
(or you failed if the correct ones he entered is less than half of the of the total number
of correct ones in the 'correct' file.

Please Chubler. Thanks so much.
# 11  
Old 11-03-2010
This should do the trick:

Code:
#!/bin/bash
eval "CORRECT=($(cat correct))"
eval "ANSWER=($(cat answers))"
TOT=${#CORRECT[@]}
echo "Your answers"
for((SCORE=QNUM=0; QNUM < TOT; QNUM++))
do
    echo "$((QNUM+1)).) ${ANSWER[$QNUM]:-none}"
    [ "${CORRECT[$QNUM]}" = "${ANSWER[$QNUM]}" ] && let SCORE=SCORE+1
done
echo
echo "You got $SCORE correct out of $TOT"
if [ $SCORE -ge $(($TOT/2)) ]
then
    echo "You Passed!"
else
    echo "You Failed"
fi

Typically I don't use for loops like the above as they only work in the bash shell, but the code to populate arrays from a file (lines 2 and 3) only work in bash anyway, so "in for a penny in for a pound".

Oh, and for your password prompting have a look "stty -echo" and "stty echo"
Code:
echo -e "Enter your password: \c"
stty -echo
read pass
stty echo


Last edited by Chubler_XL; 11-03-2010 at 07:45 PM..
This User Gave Thanks to Chubler_XL For This Post:
# 12  
Old 11-04-2010
Wow thanks so much. You are closer than a brother. Many thanks again. I will continue to study them and try out others until i become very good and 'perfect'.

I saw links to java on this our website. Do you know Java also? I need some help with classes. i.e writing good and professional classes with java doc. Please let me know. But once again, i am soo grateful.
# 13  
Old 12-14-2010
Good morning Chubler XL, hope you are alright. I have been improving my knowledge in Unix since i joined. Please i have a question regarding this script:
Code:
#!/bin/bash
ALLOW_TIME=120
eval "QUESTIONS=($(cat questions))"
eval "CORRECT=($(cat correct))"
eval "ANSWER=($(cat answers))"
PRE="$( tput sc ; tput civis ; tput cup 0 60)"
POST="$( tput el ; tput rc ; tput cnorm)"
BACK="$( tput cub1 )"
do_timer()
{
   sleep 10
   WAIT=$1
   while [ -d /proc/$WAIT ]
   do
      if [ $SECONDS -gt $ALLOW_TIME ]
      then
         kill -14 $WAIT
         break;
      fi
      show_time
      [ $(($ALLOW_TIME-$SECONDS)) -gt 90 ] && sleep 20
      sleep 2
   done
}
show_time()
{
  LEFT=$(($ALLOW_TIME-$SECONDS))
  if [ $LEFT -lt 90 ]
  then
      echo -e "${PRE}Time to go: $LEFT secs${POST}\c"
  else
      echo -e "${PRE}Time to go: $((($LEFT+59)/ 60)) mins${POST}\c"
  fi
}
timeout()
{
   echo -e "\nTime is up...Sorry"
   save_answers
}
 
ask()
{
    clear
    echo "Question $((QNUM+1)) of ${#QUESTIONS[@]}"
    show_time
    echo
    echo -e "${QUESTIONS[$QNUM]}\n"
    echo -e "Your answer: ${ANSWER[$QNUM]:- }$BACK\c"
    read new_ans
    new_ans=${new_ans:-${ANSWER[$QNUM]}}
    case $new_ans in
        a|b|c|d) ANSWER[$QNUM]=$new_ans ;;
        *) echo "Illegal answer - please try again" ;
           sleep 1 ;
           return 2 ;;
    esac
    while true
    do
        echo -e "Type n for next, p for previous, q for quit: \c"
        show_time
        read nav
        case $nav in
            n|N) return 0 ;;
            p|P) return 1 ;;
            q|Q) return 3 ;;
        esac
    done
}
trap "timeout ; exit" 14
save_answers()
{
    echo -e "\c" > answers
    QNUM=0
    SCORE=0
    while [ $QNUM -lt ${#QUESTIONS[@]} ]
    do
        echo "\"${ANSWER[$QNUM]}\" " >> answers
        [ "${CORRECT[$QNUM]}" = "${ANSWER[$QNUM]}" ] && let SCORE=SCORE+1
        let QNUM=QNUM+1
    done
    echo "You got $SCORE questions correct out of ${#QUESTIONS[@]}"
}
do_timer $$ &
QNUM=0
while true
do
   ask $QNUM
   case $? in
       0)  let QNUM=QNUM+1 ;;  # Next
       1)  let QNUM=QNUM-1 ;;  # Prev
       3)  break ;; # Quit/Done
   esac
   [ $QNUM -ge ${#QUESTIONS[@]} ] && QNUM=0
   [ $QNUM -lt 0 ] && let QNUM=${#QUESTIONS[@]}-1
done
save_answers

it is working perfectly but there is no way to tell the user that he has reached
the last question. I have been trying for days to put some extra line of
code to prompt the user that he has reached the last and for him to enter
'q' to quit. I tried codes like:
Code:
max_questions()

{

if [ $((QNUM+1)) -eq ${#QUESTIONS[@]} ];
then
echo "end of questions. enter q to quit"
show_time
        read nav
        case $nav in	# case construct for allowable return options
            n|N) return 0 ;;
            p|P) return 1 ;;
            q|Q) return 3 ;;
        esac
fi
}

Then i put the max_question function before the after the clear command.

I also tried making this modification to the ask command which nearly worked
except that i had 8 questions and it display 7 before bringing out
the message "end of questions. enter q to quit". Here is the change i made
Code:
ask()
{
    clear
 if [ "$((QNUM+1))" -eq ${#QUESTIONS[@]} ];
then
echo "end of questions. enter q to quit"
show_time
        read nav
        case $nav in	
            n|N) return 0 ;;
            p|P) return 1 ;;
            q|Q) return 3 ;;
        esac

else
   
echo "Question $((QNUM+1)) of ${#QUESTIONS[@]}"
    
  
    show_time
    echo
    echo -e "${QUESTIONS[$QNUM]}\n"
    echo  "Enter options a,b,c or d and press the Enter key."
    echo -e "Your answer: ${ANSWER[$QNUM]:- }$BACK\c"
    read new_ans
    new_ans=${new_ans:-${ANSWER[$QNUM]}}
    case $new_ans in	
        a|b|c|d) ANSWER[$QNUM]=$new_ans ;;
        *) echo "Illegal answer - please try again" ;
           sleep 1 ;
           return 2 ;;
    esac
    while true
    do
        echo -e "Enter n for next question, p for previous, q for done: \c"
        show_time
        read nav
        case $nav in	
            n|N) return 0 ;;
            p|P) return 1 ;;
            q|Q) return 3 ;;
        esac
    done
   

fi


I tried and tried other inequality symbols and many other things to make it
show the 8th (last) question before bringing out the message but this
was the closest i could get.

Please Chubler XL what am i missing out? How can it be made to bring
out questions 1-8, and at the 8th question prompt the user that he has reach
-ed the end.

Thanks so much.

Moderator's Comments:
Mod Comment Please use code tags

Last edited by Franklin52; 12-14-2010 at 06:50 AM..
# 14  
Old 12-14-2010
In ask you want to display question 8 of 8, then read their answer and then show your new message so the updated ask function would be:

Code:
ask()
{
    clear
    echo "Question $((QNUM+1)) of ${#QUESTIONS[@]}"
    show_time
    echo
    echo -e "${QUESTIONS[$QNUM]}\n"
    echo -e "Your answer: ${ANSWER[$QNUM]:- }$BACK\c"
    read new_ans
    new_ans=${new_ans:-${ANSWER[$QNUM]}}
    case $new_ans in
        a|b|c|d) ANSWER[$QNUM]=$new_ans ;;
        *) echo "Illegal answer - please try again" ;
           sleep 1 ;
           return 2 ;;
    esac
    while true
    do
        if [ "$((QNUM+1))" -eq ${#QUESTIONS[@]} ];
        then
            echo "end of questions. enter q to quit"
        else
            echo -e "Type n for next, p for previous, q for quit: \c"
        fi
        show_time
        read nav
        case $nav in
            n|N) [ "$((QNUM+1))" -ne ${#QUESTIONS[@]} ] && return 0 ;;
            p|P) [ "$((QNUM+1))" -ne ${#QUESTIONS[@]} ] && return 1 ;;
            q|Q) return 3 ;;
        esac
    done
}

Down side of this is they don't get to go back and review/change an answer before finishing.

The version below allows them to supply the required number of answers and then asks "All done, type question (1-n) to review your answer or Q to quit:"

Code:
ask()
{
    ANSWERED=$(echo -e ${ANSWER[@]}"\c" | sed 's/ //g' | wc -c)
    if [ $ANSWERED -ge ${#QUESTIONS[@]} ]
    then
        while true
        do
            echo -e "All done, type question (1-${#QUESTIONS[@]}) to review your answer or Q to quit: \c"
            read QNUM
            [ $QNUM = "q" ] && return 3
            let QNUM=QNUM-1
            [ $QNUM -ge 0 -a $QNUM -lt ${#QUESTIONS[@]} ] && break
            echo "Illegal response"
        done
    fi
    clear
    echo "Question $((QNUM+1)) of ${#QUESTIONS[@]}"
    show_time
    echo
    echo -e "${QUESTIONS[$QNUM]}\n"
    echo -e "Your answer: ${ANSWER[$QNUM]:- }$BACK\c"
    read new_ans
    new_ans=${new_ans:-${ANSWER[$QNUM]}}
    case $new_ans in
        a|b|c|d) ANSWER[$QNUM]=$new_ans ;;
        *) echo "Illegal answer - please try again" ;
           sleep 1 ;
           return 2 ;;
    esac
    ANSWERED=$(echo -e ${ANSWER[@]}"\c" | sed 's/ //g' | wc -c)
    [ $ANSWERED -ge ${#QUESTIONS[@]} ] && return 4
    while true
    do
        echo -e "Type n for next, p for previous, q for quit: \c"
        show_time
        read nav
        case $nav in
            n|N) return 0 ;;
            p|P) return 1 ;;
            q|Q) return 3 ;;
        esac
    done
}


Last edited by Chubler_XL; 12-14-2010 at 09:28 AM..
This User Gave Thanks to Chubler_XL For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

How would I construct a (possibly simple) IF statement?

Hi all, I thought this would be simple, but I've been having a lot of trouble trying to write this IF statement, if I may ask for help pls: In BASH, how would I construct the if statement: Should ONLY be true if USEROPTscript=="yes"]] AND $mode=="INSTALL" /or/ $mode=="CHANGE" ]]... (3 Replies)
Discussion started by: jmccoughlin
3 Replies

2. Shell Programming and Scripting

Special IF construct syntax in UNIX

Hi, I don't understand && and || in this context. I thought && is for logical 'AND' and || is for logical 'OR'. && echo "Not empty" || echo "Empty" Please help Thank You (5 Replies)
Discussion started by: TomG
5 Replies

3. Shell Programming and Scripting

For loop; how to construct a array with variables

Hi everybody!! Here is the thing; I have a trouble in this simple situation, I'm trying to write an array with all the arguments of a command. I mean, if I have: ./mycommand.sh aa bb cc dd I need to take an array like this: myarray=(aa bb cc dd) So I use a simple for loop like this: for... (4 Replies)
Discussion started by: andresgom
4 Replies

4. Shell Programming and Scripting

Construct path

Hi, I need to construct the below path from the two available directory path, O/P /home/data/test/run/ht/WEB/HTML /home/data/test/run/ht/WEB/JSP /home/data/test/run/ht/WEB/CSS Path:1 ------ /home/data/test/run/ Path:2 ------ /home/data/share/app/01/lang/ht/WEB/HTML... (5 Replies)
Discussion started by: vel4ever
5 Replies

5. UNIX for Dummies Questions & Answers

awk construct unfamiliar to me

Please help me out: I've seen this construct awk '{...}1'several times, like in scrutinizer's today's post awk '{for(i=2;i<=NF;i++)if($i==$1)$i=RS $i}1' infilebut I can't find (manuals, man pages, internet FAQs,...) an explanation of what it does resp. stands for. Any hint is appreciated! (5 Replies)
Discussion started by: RudiC
5 Replies

6. Shell Programming and Scripting

construct a string with X number of spaces

I'd like to create a variable with the value of X number of space( no Perl please), printf seems to work, but , in following example,10 spaces becomes 1 space when assinged to a variable, Why? other solutions are welcome. $printf "=%10s=\n" = = $var=$(printf "=%10s=\n") echo... (4 Replies)
Discussion started by: honglus
4 Replies

7. Shell Programming and Scripting

syntax error in the if construct

Hi can anyone tell me why is this code giving error mode=$1 if ] || ] then echo "MODES:" exit 1 fi Thanks (5 Replies)
Discussion started by: Anteus
5 Replies

8. Shell Programming and Scripting

if-else construct not working

Hi all, Sorry to ask this easy question but I am stuck. In a scenario i am executing one shell script which contains a if - else construct : if ; then echo $line $line >> successful_build.txt else $line >> failed_services.txt fi explaination : if the... (5 Replies)
Discussion started by: bhaskar_m
5 Replies

9. Shell Programming and Scripting

ksh construct

Hi Guys, could someone tell me what this ksh construct does typeset -r PROG_PWD=${0%/*} does I understand the -r for readonly but I would very much appreciate a definitive account of what this will set $PROG_PWD to. If I run this at the cmd line it it gets set to /usr/bin but I would... (2 Replies)
Discussion started by: ajcannon
2 Replies

10. Shell Programming and Scripting

Problem with looping construct

Hi all I have tried to search for this, but keep getting a MySQL db connect error, so am posing the question here, and taking a risk of incurring the wrath of the mods with my first post... I have the following test script: #!/bin/bash HTTPD=`/bin/ps -axcu | /usr/bin/grep httpd... (6 Replies)
Discussion started by: mikie
6 Replies
Login or Register to Ask a Question