Problem in understanding debugging

Hi

i was going through the script debugging technique. below example was given in the book.

1   #!/bin/sh
     2
     3   Failed() {
     4   if [ $1 -ne 0 ] ; then
     5   echo "Failed. Exiting." ; exit 1 ;
     6   fi
     7   echo "Done."
     8   }
     9
    10   echo "Deleting old backups, please wait... \c"
    11   rm -r backup > /dev/null 2>&1
    12   Failed $?
    13
    14   echo "Make backup (y/n)? \c"
    15   read RESPONSE
    16   case $RESPONSE in
    17   [yY]|[Yy][Ee][Ss]|*)
    18   echo "Making backup, please wait... \c"
    19   cp -r docs backup
    20   Failed
    21   [nN]|[Nn][Oo])
    22   echo "Backup Skipped." ;;
    23  esac

my problem is when author debug the script with -nv option he is getting below o/p

[nN]|[Nn][Oo]) ./buggy2.sh: syntax error at line 21: ')'
unexpected

however when i debug the same script with same option i am getting below o/p

./debug6: 21: Syntax error: ")" unexpected (expecting ";;")

in my case i just change the name of the script.(i use debug6 and author used buggy2.sh rest i simply copy paste the script.)
why here i am getting bit more info in compare to author's o/p. is there is some problem or it is ok.

to correct the script author suggested to put (; ; after Failed in line no. 20 like below.

Failed ;;

my question is why i need to use 2 colon after Failed not one?
also how does author know just by seeing one single line(means by seeing o/p of debug) that he need to put 2 colon after Failed.

That is simply a matter of syntax of the case statement. By the way this:

[yY]|[Yy][Ee][Ss]|*)

is wrong, since it is equivalent to

*)

Hi Scrutinizer

the code is working.

[yY]|[Yy][Ee][Ss]|*)

my below question is still unanswered.

my question is why i need to use 2 colon after Failed not one?
also how does author know just by seeing one single line(means by seeing o/p of debug) that he need to put 2 colon after Failed.

is this is also due to case statement ?

Sure it is working, it is just that it is wrong. Whatever you input, it will be interpreted as "yes".

Your first question I answered.

The author sees that the shell is not expecting to see a ")" character and the author concludes that this is due to the fact that the previous part was not closed with ;; , which is a matter of syntax.

That's two semi-colons and not colons.

Because that's the syntax for terminating a block of case statements. The first semi-colon ends that particular statement and the second ends the whole case block. The second one ensures that you don't try the following case blocks.

It is also possible to try the following block/s if you replace the second semi-colon with an ampersand (I think that's called a fall-through).

var='THE UNIX AND LINUX FORUMS';

case "$var" in

 *UNIX*)   echo "Has UNIX";&

 *LINUX*)  echo "Has LINUX";;

 *FORUMS*) echo "HAS FORUMS";;

esac

produces

Has UNIX
Has LINUX

;& is bash 4.0. The OP states #!/bin/sh

Oops, I didn't see the shebang line. By the way, it's not bash-specific; also works in ksh88/93.

ksh93 yes, but not ksh88 ..

It does work in ksh88 ( Version M-11/16/88f ).

Hi Elixir

your response help me a bit .
still i have some doubt. i hope my question will not irritate you.

  1. i understand that 1st semi colon is for ending the statement, but we usually use semi colon when we are writing 2 command on the same line. which is not the case here.

2 ok i understand that second semi colon is for case statement, i didn't understand from the below line.

The second one ensures that you don't try the following case blocks.

@elixir: This is getting a bit OT, but it was an undocumented feature in some late versions of ksh88.

Hi Elixir

your response help me a bit .
still i have some doubt. i hope my question will not irritate you.

  1. i understand that 1st semi colon is for ending the statement, but we usually use semi colon when we are writing 2 command on the same line. which is not the case here.

2 ok i understand that second semi colon is for case statement, i didn't understand from the below line.

The second one ensures that you don't try the following case blocks.