Bourne Shell Calendar

Dear Experts,

I am currently taking a unix class and we were given the code below and we were asked to modify the script so it does the following:
1) chmod u+x myCal
2) ./myCal oct nov          # this would display the calendar for october and november of the the current year
3) ./myCal oct - dec        # this would display the calendar for october through december of the current year
4) ./myCal oct nov 1982  # this would display the calendar for october and november for year of 1982

QUESTION: my question to you is how do I make a iterator that counts how many fields of text were entered after executing ./myCal because I was thinking of writing a loop that until an integer(year) is entered, it sets the previous fields as the month and then it sets the integer=year.  Or maybe someone can think of a better approach?

For example:
./myCal jan mar aug sep 1982    # there are 5 fiels after the execution of myCal

Thanks a lot guys/girls,
James
The n00b @ shell programming
-----------------------------------------------------------------------------------------------------
case $# in                                        # Let the name of this file be "myCal"
0)      set `date`; m=$2; y=$6;;        # no args: use today
1)      m=$1; set `date`; y=$6;;        # 1 arg: use this year
*)      m=$1; y=$2;;
esac

case $m in
jan*|Jan*)      m=1;;
feb*|Feb*)      m=2;;
mar*|Mar*)      m=3;;
apr*|Apr*)      m=4;;
may*|May*)      m=5;;
jun*|Jun*)      m=6;;
jul*|Jul*)      m=7;;
aug*|Aug*)      m=8;;
sep*|Sep*)      m=9;;
oct*|Oct*)      m=10;;
nov*|Nov*)      m=11;;
dec*|Dec*)      m=12;;
[1-9]|10|11|12);;                        # numeric month
*)              y=$m; m="";;            # plain year
esac

/usr/bin/cal $m $y                      # run the real one
-----------------------------------------------------------------------------------------
LVL 1
Charley420Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

guynumber5764Commented:
I tend to get my shells all mixed up but in bash (which is a sh derivative) you need a loop like...

for i in $* ; do
...
done

or else one using the parameter shift operator.  If you can find a directory containing a lot of scripts (like /etc/init.d) and you have a vague idea what you want, you can often use grep and view to determine the exact syntax needed.
sunnycoderCommented:
I think you need something like

#!/bin/bash

i=$#
echo $i
while [ $i -ne 0 ]
do
      val=$$i
      echo $val
      let i=$i-1
done

problem is $$i is not recognized by shell as such ... there was some syntax for telling the shell that there is an indirection in variables ... I had done this quite sometime ago and I can't recollect :o( ... try some advanced tutorial or reference manual

basically above loop will get you the command line parameters in the reverse order ... since year, if present, will be your last parameter, you can parse your parameters from the end ... check the last parameter against a regex like [0-9].* to determine if it is a numerical string
Charley420Author Commented:
# Unfortunately the professor specifically asked us to write everything in the bourne shell, but this is what I end up
# handing in as my assignment it works w/ the user constrain of asking them to enter in the year as oppose
# to writing the script to recognize whether the user entered in a integer or string.
# ./myCal sep - nov or ./myCal 9 - 11
# ./myCal sep oct nov
# Source: Kernighan and Pike
iterator=0
multiple=0
dash='-'
numoffield=0

echo Please enter the month you would like to see
echo If you would like to see multiple months please enter them using the syntax below
echo ./myCal jan - mar
echo The program will ask you for the year at the end

case $# in
0)      set `date`; m=$2; y=$6; numoffield=0;;  # no args: use today
1)      m=$1; set `date`; y=$6; numoffield=1;;  # 1 arg: use this year
2)      m=$1; m1=$2 numoffield=2;;
3)      m=$1; m1=$2; m2=$3; numoffield=3;;
*)      m=$1;   y=$2;;
esac

case $m in
jan*|Jan*)      m=1;;
feb*|Feb*)      m=2;;
mar*|Mar*)      m=3;;
apr*|Apr*)      m=4;;
may*|May*)      m=5;;
jun*|Jun*)      m=6;;
jul*|Jul*)      m=7;;
aug*|Aug*)      m=8;;
sep*|Sep*)      m=9;;
oct*|Oct*)      m=10;;
nov*|Nov*)      m=11;;
dec*|Dec*)      m=12;;
[1-9]|10|11|12);;
*)              m="";;
esac

case $m1 in
jan*|Jan*)      m1=1;;
feb*|Feb*)      m1=2;;
mar*|Mar*)      m1=3;;
apr*|Apr*)      m1=4;;
may*|May*)      m1=5;;
jun*|Jun*)      m1=6;;
jul*|Jul*)      m1=7;;
aug*|Aug*)      m1=8;;
sep*|Sep*)      m1=9;;
oct*|Oct*)      m1=10;;
nov*|Nov*)      m1=11;;
dec*|Dec*)      m1=12;;
[1-9]|10|11|12);;                       # numeric month
*)              y=$m1; m1="";;            # plain year
esac

case $m2 in
jan*|Jan*)      m2=1;;
feb*|Feb*)      m2=2;;
mar*|Mar*)      m2=3;;
apr*|Apr*)      m2=4;;
may*|May*)      m2=5;;
jun*|Jun*)      m2=6;;
jul*|Jul*)      m2=7;;
aug*|Aug*)      m2=8;;
sep*|Sep*)      m2=9;;
oct*|Oct*)      m2=10;;
nov*|Nov*)      m2=11;;
dec*|Dec*)      m2=12;;
[1-9]|10|11|12);;                       # numeric month
*)              y=$m2; m2="";;            # plain year
esac

echo Please enter the year that the above month are in?
read y

while [ $2 == '-' ]
do
        while [ $m -ne $m2 ]
        do
                /usr/bin/cal $m $y
                m=`expr $m + 1`
        done
        /usr/bin/cal $m2 $y
        exit
done

case $numoffield in
        0)/usr/bin/cal;;
        1)/usr/bin/cal $m $y;;
        2)/usr/bin/cal $m $y; /usr/bin/cal $m1 $y;;
        3)/usr/bin/cal $m $y; /usr/bin/cal $m1 $y;/usr/bin/cal $m2 $y;;
esac

exit 0
cluedonCommented:

you need to loop through $* and call cal for all but the last argument.   $* contains all
the command line arguments, $# contains the number of arguments.   You can get the
last argument using either awk (  echo $* | awk '{print $NF}' ) or cut (last=`echo $* | cut -d" " -f$#`).      I also moved the case check into a function to make the loop a little easier to understand, but some prof's hate global vars, even in shell scripts, so you may want to put the case check into the loop.

Try this...


#!/bin/sh

set_month()
{
  m=$1  #$0 is the first arg to the function

  #set global variable month
  case $m in
    jan*|Jan*)      month=1;;
    feb*|Feb*)      month=2;;
    mar*|Mar*)      month=3;;
    apr*|Apr*)      month=4;;
    may*|May*)      month=5;;
    jun*|Jun*)      month=6;;
    jul*|Jul*)      month=7;;
    aug*|Aug*)      month=8;;
    sep*|Sep*)      month=9;;
    oct*|Oct*)      month=10;;
    nov*|Nov*)      month=11;;
    dec*|Dec*)      month=12;;
    [1-9]|10|11|12);;                        # numeric month
    *)              y=$m; month="";;            # plain year
  esac

}

##get the number of arguments
# might use args=`echo $* | wc -w`
args=$#


##get the last argument, the year
# if you like awk use last=`echo $* | awk '{print $NF}' `
last=`echo $* | cut -d" " -f$#`
year=$last

echo "list is $* "
for arg in $*
do
  if [ $arg = $year ]
  then :    #last arg, just skip
  else
    echo processing $arg $year...
    set_month $arg
    echo /usr/bin/cal $month $year
   /usr/bin/cal $month $year                      # run the real one
  fi

done

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming

From novice to tech pro — start learning today.