1

Code:

#!/bin/csh

if ( A$1 == A ) then
    echo ""
    echo "LIST <name>"
    echo ""
    exit
endif

..............

Ok this is a sample from a bigger script I got. The scripts starts with this piece of code and it is not related to any of the code that follows afterwards.

The script usage is like: LIST 'name', where LIST is the script command and 'name' is a certain constant introduced by the user.

What I know until now is that if I run the script like this:

LIST 'name'

the script will do it's job with the constant 'name' but if I run without 'name' like this:

LIST

it will show:

LIST <name>

like a short description on how to use the command. This description is from the echo inside if.

What I need to understand is what this line does:

if ( A$1 == A ) then

Thanks!

countermode
  • 7,533
  • 5
  • 31
  • 58
Future
  • 179

4 Answers4

4

This make sure that $1 is not empty string. If $1 is empty string, then if condition is:

( A == A )

evaluated to true. This is a workarround to make sure you don't have an syntax error. If you simply do:

if ( $1 == "" )

When $1 is empty string, this expression become ( == "" ) causes a syntax error.

At least in bsd-csh, tcsh, ( $1 == "" ) works. With original csh, you should use:

if ( "A$1" == "A" )

A note that you should always double quotes your variable, see explanation here. In csh, if variable $a contains newline, then "$a" won't work, you need $a:q.

cuonglm
  • 153,898
  • For null read empty string. They are not the same thing. – ctrl-alt-delor Aug 28 '14 at 16:04
  • @richard: Can you make it more clear? What "null read empty string" means? – cuonglm Aug 28 '14 at 16:07
  • @Gnouc "Where Gnouc wrote null string in his answer, read empty string instead." - richard emphasizes the difference between a null string, and an empty string. – John WH Smith Aug 28 '14 at 18:05
  • @JohnWHSmith: Does null string different with empty string in shell? – cuonglm Aug 28 '14 at 18:07
  • @Gnouc In this very example, it is about checking string emptiness (concatenating with a, using == ""). I believe a null string is what triggers the ( == "") error you're mentioning in your answer (undefined variable, perhaps?). I don't know how things are handled by bash internally, so this is nothing more than an assumption. – John WH Smith Aug 28 '14 at 18:14
  • @JohnWHSmith: (1) This question is about csh, not bash. (2) In either shell, LIST and LIST "" are going to be treated the same by any of the code currently on this page. Telling them apart requires looking at $#argv (in csh) or $# (in bash), or doing even trickier stuff that I won't get into here. – G-Man Says 'Reinstate Monica' Aug 28 '14 at 18:59
0

I believe the if loop is used as a way to test if the arguments are passed or not to the script. Though technically it is the purpose of the if loop, I think it would be more apt to say it is used to check if the $1 is empty or not. For example, I copied the script and invoked it as,

script "some_argument"

As expected, it doesn't go inside the if loop. Now, if I invoke it without any parameter as,

script

I get the output as, LIST <name>

So, I added an echo statement just before the if loop to check the arguments passed to the script. So, if I invoke the script without any argument it will go inside the if loop.

Also, A$1 == A is just something to test if $1 is empty or not. Even if you have something like, somethingvalid$1 == somethingvalid and invoke the script as script, it will still get inside the if loop and print the output.

Ramesh
  • 39,297
  • It only check if $1 is null or not. This is a case when $1 is passed as null string. – cuonglm Aug 28 '14 at 15:05
  • @Gnouc, yeah. Though, in general, it would be used as a test case to check if the argument is passed or not. However, I included the modifications as suggested. – Ramesh Aug 28 '14 at 15:10
  • 2
    if is selection not iteration: not a loop. You could say “if block” (both iteration and selection have a predicate and statement block. OR just say “if”. – ctrl-alt-delor Aug 28 '14 at 16:07
0

This line checks if $1 is empty. $1 is the first parameter passed to the script by user when running the script on the command line. If $1 is empty, then nothing is appended to the letter A and A == A is true.

  • "$1 is the first parameter passed to the script by user". very well said. why didn't i thought of this. it all makes sense now. thank you! – Future Aug 28 '14 at 15:14
0

Gnouc makes an important point without stressing it: whenever you reference a shell variable ($identifier, e.g., $futur) or a positional parameter ($digit, e.g., $1), you should enclose it in double quotes (e.g., "$1") unless you have a good reason not to and you’re very sure you know what you’re doing.  Constant strings with no special characters (e.g., A, foo, or bar) don’t need to be quoted, but it doesn’t hurt.  Quoted strings can be concatenated and combined; e.g., "foo""bar" is equivalent to "foobar", and A"$1" is equivalent to "A""$1" and hence "A$1".

  • Quotes preserve the existence of empty strings. As Gnouc explains, if your script said

    if ( $1 == "" )
    

    and you invoke it without arguments,

    LIST
    

    or with an explicit empty string argument,

    LIST ""
    

    then the if statement will be “expanded” as

    if ( == "" )
    

    which causes a syntax error.

  • Quotes preserve the integrity of strings with spaces or special characters.  If you invoke your script with an argument containing a space,

    LIST "foo bar"
    

    then the if statement (if ( A$1 == A )) will be expanded as

    if ( Afoo bar == A )
    

    which causes a syntax error.  Similar results happen if you invoke your script with an argument containing a quoted wildcard:

    LIST "foo*"
    

But nobody has explained why the script doesn’t just say

if ( "$1" == "" )

In previous versions of csh, if you invoke your script with this argument,

LIST ==

then the if statement will be expanded as

if ( "==" == "" )

which also caused a syntax error.  People wrote their if statements with protection for positional parameters (and, when appropriate, shell variables / environment variables), like A$1 or "A$1", to prevent arguments (operands) from looking like operators (particularly /, also +, -, and *) and causing the parser to be confused.  This seems to have been fixed (at least in some versions of csh / tcsh).  I just tried this in my (Cygwin’s) version of tcsh:

$ if ( == == "" ) echo yes
if: Expression Syntax.
$ if ( == == == ) echo yes
if: Expression Syntax.
$ if ( "==" == "" ) echo yes
                                <--- (no output)
$ if ( "==" == "==" ) echo yes
yes
$ if ( / == / ) echo yes
Division by 0.
$ if ( "/" == "/" ) echo yes
yes

so,

  • Quotes can tell the if command in tcsh that an argument is an operand and not an operator.
  • @Gnouc: (1) Since the shell code at the focus of the question, if ( A$1 == A ), breaks if $1 contains space(s) or wildcard(s), and you suggested the fix for that, I thought it was worthwhile to explain why you were suggesting it. – G-Man Says 'Reinstate Monica' Aug 28 '14 at 18:08
  • @Gnouc: (2a) I didn't make the "null read empty string" comment; that was richard. (2b) I guess that he means that the OP and other readers should pretend that you said "empty string" where you actually said "null" or "null string", because "They are not the same thing" (his words). I would agree with him, in the context of a C/C++ program, and maybe even in some shell situations (e.g., lsls ""), but I believe that it's a distinction without a difference in this context. – G-Man Says 'Reinstate Monica' Aug 28 '14 at 18:09
  • Oh, so sorry for my confusion, maybe I'm too sleep. I'm going to update my answer. – cuonglm Aug 28 '14 at 18:15