0

I was learning bash when I stuck comparing strings inside if statement.

Script: shiftDemo.sh

  1 #!/bin/bash
  2 
  3 #using shift keyword to shift CLA 
  4 
  5 while true
  6 do
  7         if [ "$1" = "" ]     #change this statement wrt below cases
  8         then
  9                 exit
 10         fi
 11         echo '$1 is now ' "$1"
 12         shift
 13 done

I used the following methods:

1.if (( "$1" = "" ))

2.if [ "$1" = "" ]

Observations:

1a) $ bash shiftDemo.sh first second third

`shiftDemo.sh: line 7: ((: =  : syntax error: operand expected (error token is "=  ")`

1b) $ sh shiftDemo.sh first second third

shiftDemo.sh: 7: shiftDemo.sh: first: not found
$1 is now  first
shiftDemo.sh: 7: shiftDemo.sh: second: not found
$1 is now  second
shiftDemo.sh: 7: shiftDemo.sh: third: not found
$1 is now  third
shiftDemo.sh: 7: shiftDemo.sh: : Permission denied
$1 is now  
shiftDemo.sh: 12: shift: can't shift that many

2)In this case, if statement runs fine with both the shells & gives correct output.

$ bash shiftDemo.sh first second third
$1 is now  first
$1 is now  second
$1 is now  third

$ sh shiftDemo.sh first second third
$1 is now  first
$1 is now  second
$1 is now  third

Based on the above observations, my doubts are:

  1. What is wrong with case 1. How can I correct it (I want to use C style syntax throughout my script).

  2. Which syntax is preferred so that it will work with both sh & bash shell ?

2

1 Answer 1

2

In bash, the (( ... )) notation is dedicated to arithmetic evaluation (see the ARITHMETIC EVALUATION section of the man page). When executing:

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

for the first time, you try to assign variable first with nothing instead of the expected integer value, just like if you were executing:

if (( first = ))

which does not make sense, thus the error message. So, to test if a bash variable is assigned a value different from the empty string, you can use the test external command, that is, your [ ... ] notation. Type man test to see what test can do. You can use any of:

if [ -z "$1" ]
if test -z "$1"
if [ "$1" = "" ]
if test "$1" = ""
if [ "X${1}X" = "XX" ]
if test "X${1}X" = "XX"
...

It is difficult to tell what (( ... )) does with your sh: on most systems, sh is not the original Bourne Shell any more. It is sometimes bash (that behaves differently when invoked as sh), or dash, or something else. You should thus first check what sh is on your system.

Anyway, if test is also an external command of your sh (whatever your sh is), the best is to use it: by construction, it will behave the same. The only potential difference will be the syntax of the if control structure.

Not the answer you're looking for? Browse other questions tagged or ask your own question.