Check for spaces in input argument!

Hi guys,
I have created a csh script which allows user to pass input argument with the script like:

cluster_on_lev3.csh  -t <value> -p <value>
Example: 
cluster_on_lev3.csh  -t 2.3 -p 0.05

Now I want to create an error code where if user passes input argument without spaces , the code should exit. Example: cluster_on_lev3.csh -t2.3 -p0.05. In this situation where the space is missing after -t and -p, the code should exit.
Thank you very much in advance.

Programming in csh is very much not reccomended. It is an obsolete and very faulty shell which people just refuse to stop using... These are not bugs but insurmountable design flaws. Every variety of UNIX comes with the Bourne shell, it wouldn't be UNIX if it didn't, you'd do well to learn it.

Show your code.

The whole code is:

#!/bin/csh
if (${#argv} < 1) then
    USAGE:
    echo "USAGE: cluster_on_lev3.csh -dir <full_path Lev3 gfeat cope directory> [options]"
    echo "USAGE: cluster_on_lev3.csh -dir <full_path Lev3 gfeat cope directory> -t <value> -p <value> -c <value> -l <value> -h <value>"
exit -1 
endif
while ( $#argv != 0)
	set flag = $argv[1]; shift;
	switch ($flag)
	case "-dir":
	    set lev3cope = $argv[1]; shift;
	    breaksw
	case "-t":
	    set thresh = $argv[1]; shift;
	    breaksw
	case "-p":
            set pvalue = $argv[1]; shift;
	    breaksw
	case "-c":
            set conn_voxels = $argv[1]; shift;
	    breaksw
	case "-l":
            set zmin = $argv[1]; shift;
	    breaksw
	case "-h":
            set zmax = $argv[1]; shift;
	    breaksw
	endsw
end

I just want to put a check to make sure the sure is passing input argument with the space i.e -t 2.3 instead of -t2.3

How does this work:

#!/bin/csh
if (${#argv} < 1) then
    USAGE:
    echo "USAGE: cluster_on_lev3.csh -dir <full_path Lev3 gfeat cope directory> [options]"
    echo "USAGE: cluster_on_lev3.csh -dir <full_path Lev3 gfeat cope directory> -t <value> -p <value> -c <value> -l <value> -h <value>"
exit -1 
endif
while ( $#argv != 0)
	set flag = $argv[1]; shift;
	switch ($flag)
	case "-dir":
	    set lev3cope = $argv[1]; shift;
	    breaksw
	case "-t":
	    set thresh = $argv[1]; shift;
	    breaksw
	case "-p":
            set pvalue = $argv[1]; shift;
	    breaksw
	case "-c":
            set conn_voxels = $argv[1]; shift;
	    breaksw
	case "-l":
            set zmin = $argv[1]; shift;
	    breaksw
	case "-h":
            set zmax = $argv[1]; shift;
	    breaksw
        default:
            echo "Unknown option" $argv[1]
            exit 1
            breaksw
	endsw
end

The way it works is:
Example: If the user types:

cluster_on_lev3.csh -dir /home/shared -t 2.3 -p 0.05 -c 26 -l 2"

The above code checks for arguments such as -dir, -t, or -c in the Case statement and shifts to set the input variable passed by the user. I also have the part of the code to have the default values when the argument is not been used.
All I want is to prompt the user in case he didn't use the space with the argument. That is the code exits when user passed:

 cluster_on_lev3.csh -dir /home/shared -t 2.3 -p 0.05 -c26 (incorrect) -l2 (incorrect)

I understand moving away from csh is the best way and I am migrating to bash, but this is someone else's script and I have been asked to do modifications. Thanks for understanding.

Yes, so have you tried the script I gave you... It should flag any arguments it doesn't recognize.

Hi, Sorry about this but I didn't receive any script from you. Pardon me if I have missed something in your email.

Read the forum thread, please.

Thank you for your response. I guess this partially work, but I was more looking for an error prompt to the user like:

cluster_on_lev3.csh -dir /home/shared -t 2.3 -p 0.05 -c26  -l2 
"Incorrect use of argument"

Thank you for your help!

So, change the text "unknown option" into "incorrect use of argument"...

Unfortunately the error message which i get is:

argv: Subscript out of range

I use ksh and bash; not csh. And, I strongly prefer utilities that accept, but do not require, space between an option-letter and its option-argument. But, if I understand what you're trying to do, just change:

	case "-h":
            set zmax = $argv[1]; shift;
	    breaksw
	endsw

to:

	case "-h":
            set zmax = $argv[1]; shift;
	    breaksw
        case "*":
            echo "Incorrect use of argument: $flag"
            breaksw
	endsw
1 Like

Thank you so much. This is what I was looking for.:slight_smile:

while ( $#argv != 0)
	set flag = $argv[1]; shift;
	switch ($flag)
	case "-dir":
	    set lev3cope = $argv[1]; shift;
	case "-h":
            set zmax = $argv[1]; shift;
	    breaksw
        case "*":
            echo "Incorrect use of argument: $flag"
            breaksw
	endsw

Besides its CSH which i dont know, i'd understand the 'set' line, as the variable "flag" becomes the value of the array argv[1].
Which in turn would let you use $flag over $argv[1] on each call, or am i misunderstand that set flag = argv[1];shift

Took me just 10 years to get near the though i'd finaly understand 'shift', but this line.

Just trying to learn.

If you look at the usage statements this script prints:

echo "USAGE: cluster_on_lev3.csh -dir <full_path Lev3 gfeat cope directory> [options]"
echo "USAGE: cluster_on_lev3.csh -dir <full_path Lev3 gfeat cope directory> -t <value> -p <value> -c <value> -l <value> -h <value>"

you might notice that this script requires its options and option arguments to be presented as separate arguments. When a command line is presented as expected, flag will be set to an option introducer -dir , -t , -p , etc. The shift then removes the option introducer from the list of remaining arguments and $argv[1] refers to the option-argument corresponding to that option introducer. The switch statement then sets a variable corresponding to the given option introducer to the value of the option-argument (which is then also shifted off of the remaining list of unprocessed arguments).

Note that each case can do a shift in addition to the shift after picking up the option introducer because every option in this script requires an option-argument.

The command:

echo "Incorrect use of argument: $flag"

is only printed when an option introducer is found on the command line that does not match an expected option.

1 Like

Until now i used either arrays to parse the args (compare item with string '-h') and do action (or set variable) of array(+1), skipping i and i+1 after or even worse (but most used - lazy) hard coded argument positions....

eg - pseudo code - tired:

i=0
ARGS=($@)
for cur in $(seq 0 1 $#@);do
   ((i++))
   case "${ARGS[$cur]}" in
   "-h") echo "help" ;;
   "-o") echo other
         otherValue=${ARGS[$i]}
         unset ARGS[$i] ARGS[$cur] ;;
   *) echo "no args, or unhandled) ;;
    esac
done

This switch method kind of sounds faster.

Did i understand this properly (simplified?):
We're switching the flag, which is the actual argument trigger/toggle/(lost in translation), while argv[1] is the actual current value to be set as variable?

I was merely trying to explain what this csh script was doing.

I do not approve of this method of parsing command line options and option-arguments.

When using standards conforming shells (such as ksh and bash ), you can use the getopts shell built-in so any shell script can parse options just like standards-conforming utilities are required to do. For instance, if a utility has a -h option (which does not take an option-argument) and a -f option (which takes a filename as an option-argument), a shell script should be able to recognize any of the following as equivalent ways to specify both options and to recognize that -x is an operand (not an option):

scriptname -h -f file -- -x
scriptname -f file -h -- -x
scriptname -h -ffile -- -x
scriptname -ffile -h -- -x
scriptname -hf file -- -x
scriptname -hffile -- -x

You can write a shell script ( bash , csh , ksh , etc.) to do this type of command line argument processing without using getopts , but few programmers make it work with the same look and feel as that provided by standard utilities. Why reinvent the wheel or limit the way in which your script recognizes command line options when getopts can be used to make your script handle command line options the same way almost all of the standard UNIX utilities handle command line options?

For an example using the getopts shell built-in, check out the EXAMPLES section of the getopts(1) man page.

1 Like