I shoe here the start of a csh script I have written. I am trying to write some code to check the arguments and if the arguments don't match the tags, I will abort and display an error.
For example using
./script.csh -r=10/20.30/40 -xyz=2/3/4
will give an error as the -xyz tag doea not exist.
set ierr = 0
set iarg = 0
set opt_jbase = 0
set opt_range = 0
set opt_annot = 0
set opt_fout = 0
set opt_vrb = 0
set opt_usage = 0
set opt_examples = 0
set opt_help = 0
set fullnames_list = ""
set fnames_list = ""
set fext_list = ""
set nf = 0
set Version = "V04"
alias MATH 'set \!:1 = `echo "\!:3-$" | bc -l`'
set narg = $#argv
while ($iarg < $narg)
MATH iarg = $iarg + 1
set arg = $argv[$iarg]
set opt = `echo $arg | awk 'BEGIN {FS="="} {print $1}'`
set par = `echo $arg | awk 'BEGIN {FS="="} {print $2}'`
switch ($opt)
case "-jb":
set Ajbase = $par
set bwidth = `echo $Ajbase | awk '{split($1,a,"/"); print a[1]}'`
set bheight = `echo $Ajbase | awk '{split($1,a,"/"); print a[2]}'`
set opt_jbase = 1
breaksw
case "-r":
set Arange = $par
set xmin = `echo $Arange | awk '{split($1,a,"/"); print a[1]}'`
set xmax = `echo $Arange | awk '{split($1,a,"/"); print a[2]}'`
set ymin = `echo $Arange | awk '{split($1,a,"/"); print a[3]}'`
set ymax = `echo $Arange | awk '{split($1,a,"/"); print a[4]}'`
set opt_range = 1
breaksw
case "-a":
set Aannot = $par
set adx = `echo $Aannot | awk '{split($1,a,"/"); print a[1]}'`
set ady = `echo $Aannot | awk '{split($1,a,"/"); print a[2]}'`
set afx = `echo $adx | awk '{print $1/2}'`
set afy = `echo $ady | awk '{print $1/2}'`
set ax = "a"$adx"f"$afx
set ay = "a"$ady"f"$afy
set opt_annot = 1
breaksw
case "-fout":
set Afout = $par
set fout = `echo $Afout | awk 'BEGIN { FS=".ps" } { print $1 }'`
set opt_fout = 1
breaksw
case "-v":
set opt_vrb = 1
breaksw
case "-usg":
set opt_usage = 1
breaksw
case "-eg":
set opt_examples = 1
breaksw
case "-h":
set opt_help = 1
breaksw
default:
set filename = `echo $arg | awk 'BEGIN {FS="."} {print $1}'`
set filextension = `echo $arg | awk 'BEGIN {FS="."} {print $2}'`
set fullnames_list = "$fullnames_list $arg"
set fnames_list = "$fnames_list $filename"
set fext_list = "$fext_list $filextension"
MATH nf = $nf + 1
endsw
end # while
Sorry. Couldn't find the question. What follows is just my guess at what you may want:
The processing under the 'default' tag in your switch looks like a pre-processing block that should be done before entering the switch. Your instructions inside the switch do something for each and every valid argument given, so your 'default' tag should be considered an 'otherwise' tag instead and include there whatever error processing you have in mind when the user inputs an illegal argument.
Problem is you may have already done some processing before an invalid tag is discovered. If the script then bombs out with an invalid arguments error some work has already been done. This different to how every other unix command operates, and is quite dangerous.
As DGPickett implied, try to validate all the arguments first and then do the processing. Consider using getopt to simplify the argument parsing.
Yes, some things would have already been done, but it will only be about processing the information given (declaration of variables). So it does not matter if I stop and exit.
I use the dafault to pass filenames (no tags are used when passing certain files).
Can you give a small example that I can follow Chub?
Yep, I didn't read you code closely enough. All the awk scripts are just pulling apart your arguments. Might be better to drop the = part and put parameter in next arg (this is the unix standard way) eg:
./script.csh -r 10/20.30/40 -xyz 2/3/4
This might get you started:
#!/bin/csh
set done=0
set opt_vrb
set ajbase
while ( $#argv != 0 && $done == 0 )
switch ($1)
case -jb:
if ( $2 == "") then
echo "option -jb requires argument"
exit 2
endif
set ajbase=$2
shift
breaksw
case --:
set done=1
breaksw
case -v:
set opt_vrb=1
breaksw
default:
set F=`expr substr $1 1 1`
if ( "$F" == "-" ) then
echo "Invalid argument $1"
exit 2
endif
set done=1
breaksw
endsw
if ( $done == 0 ) then
shift
endif
end
if ( $opt_vrb == 1) then
echo -v option set
endif
if ( "$ajbase" != "" ) then
echo ajbase=$ajbase
endif
echo File Arguments left: $argv
getopt works OK in csh but you will need to use single char flags (but I personally perfer single char args).
As you can see getopt cuts a lot of the mucking around out as it checks the parameters for you
#!/bin/csh
set ajbase
set arange
set opt_v
set opt_u
set opt_e
set argv=`getopt j:r:vue $*`
if ( $status != 0 ) then
exit 1
endif
while ( "$1" != "--" )
switch ($1)
case -r:
set arange=$2
shift
breaksw
case -j:
set ajbase=$2
shift
breaksw
case -v:
set opt_v=1
breaksw
case -u:
set opt_u=1
breaksw
case -e:
set opt_e=1
breaksw
endsw
shift
end
shift # skip --
if ( $opt_v == 1) then
echo -v option set
endif
if ( "$ajbase" != "" ) then
echo ajbase=$ajbase
endif
echo File Arguments left: $argv
Check your man on getopt as some modern OS's (eg linux) support long options and have the -a flag to getop that allows long options with a single '-'. But then again if you were on a modern OS you probably wouldn't be using csh anyway.
eg:
set argv=`getopt -a -l jb: r:vue $*`
...
case --jb:
set ajbase=$2
....
I agree with cfajohnson that you will be much better off sticking to a POSIX shell, if your worried about ksh93 availablility use ksh88 and call bc or awk to do the floating point stuff.