views:

1127

answers:

6

I wrote a function in bash script. However, it's complaining about syntax. I really can't see what is it..... the error message is [: missing `]'

addem() {
            if [ $# -eq 0] || [ $# -gt 2 ]
            then
                    echo -1
            elif [ $# -eq 1 ]
            then
                    echo $[ $1 + $1 ]
            else
                    echo $[ $1 + $2 ]
            fi
    }
+3  A: 

Try:

if [ $# -eq 0 ] || [ $# -gt 2 ]

(There was no space between 0 and ].)

Sean Nyman
+1  A: 

Bash is sensitive to spaces. In your first line, replace if [ Y -eq X] with [ Y -eq X ] (space before the "]")

Steve B.
+8  A: 

You need a space before the first ]. That is:
change:
if [ $# -eq 0] || [ $# -gt 2 ]
to:
if [ $# -eq 0 ] || [ $# -gt 2 ]

pugmarx
A bit of history: this is because '[' was historically not a shell-built-in but a separate executable that received the expresson as arguments and returned a result. If you didn't surround the '[' with space, the shell would be searching $PATH for a different filename (and not find it).
Andrew Medico
+1  A: 

You should avoid brackets and use test instead:

if test $# -eq 0 || test $# -gt 2
then
 echo -1
elif test $# -eq 1
then
 echo $(( $1 + $1 ))
else
 echo $(( $1 + $2 ))
fi

Getting a better shell style will make you much better. :)

hendry
No, you should use double brackets instead of either test or single brackets.
Dennis Williamson
+2  A: 

indyK1ng: The "#" is not treated as a comment, since the "$" escapes the next character. The "$#" is an internal variable representing the number of positional parameters that exist at the current context. This can be thought of as the number of command line arguments to the shell script, but that array can be reset using the "set -- [args]" built in.

Joakim Elofsson: The overall structure of the if statement is correct, the ";" is only required before the "then" and before the "fi" if those are not listed on a separate line.

The problem is the space between the "0" and the bracket. Bash requires that brackets used to delimit conditional expressions be set off with at least a single space from the expression.

        if [ $# -eq 0] || [ $# -gt 2 ]    # Wrong

        if [ $# -eq 0 ] || [ $# -gt 2 ]    # Correct

On an additional note, the two conditional expressions can be combined. The operator association will ensure that everything works out.

        if [ $# -eq 0 -a $# -gt 2 ]   # Even Better

I tend to prefer the expanded features offered with double brackets for expression evaluation. Note that the combination of the two evaluations is done with a different operator. I find this to be more readable.

        if [[ $# -eq 0 || $# -gt 2 ]]   # My preference

Later in the script, the use of single brackets for integer addition is not recommended. The single brackets are evaluating an expression to a boolean. Double parens are used for integer math.

                echo $[ $1 + $1 ]   # Evaluation of an expression

                echo $(( $1 + $1 ))   # Integer math
semiuseless
+1  A: 

I would use extended test constructs (BASH) as demonstrated bellow. I think it would reduce the no of characters and increase readability (at least for programmers). :-)

addem() { 
        if (( $# == 0 || $# > 2 )) 
        then 
                echo -1 
        elif (( $# == 1 )) 
        then 
                echo (( $1 + $1 )) 
        else 
                echo (( $1 + $2 ))
        fi 
 }
Jayan
why the backticks ?