1. Overview

In this tutorial, we’ll look at the “unary operator expected” problem, often encountered while evaluating expressions in conditional statements. First, we’ll discuss what’s causing it. Then, we’ll discuss a few solutions that will help us to solve this issue.

2. What Causes the Error

First, let’s write a helper script, which tests whether the number entered by the user is equal to 1:

$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if [ $num1 -eq 1 ]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi

Now that we have the script, let’s test it:

$ ./unity_check.sh
Enter the input: 5
Not equal to One !!

So far, so good! Let’s also test the case when the user hits the enter key without specifying the input:

$ ./unity_check.sh
Enter the input:
./unity_check.sh: line 3: [: -eq: unary operator expected
Not equal to One !!

Notably, the script fails, citing “unary operator expected” as the reason. Furthermore, let’s debug the script to identify the root cause:

$ bash -xv ./unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
+ read -p 'Enter the input: ' num1
Enter the input:
if [ $num1 -eq 1 ]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi
+ '[' -eq 1 ']'
./unity_check.sh: line 3: [: -eq: unary operator expected
+ echo 'Not equal to One !!'
Not equal to One !!

As we can see from the debug output, the if statement evaluates to:

if [ -eq 1 ]

Here, due to the blank value in the variable, the left side of the comparison expression disappears. In effect, we’re left with a single argument for the equality check (eq) operator. The eq operator is a binary operator and needs two arguments, therefore, Bash complains with “unary operator expected”.

We’ll check the possible solutions to handle this error in the next sections.

3. Preventing the Error by Quoting the Variables

We can double-quote our variables to prevent word splitting, which occurs during shell expansion. Let’s go ahead and modify our original script:

$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if [ "$num1" -eq 1 ]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi

Here, we’ve changed $num1 to “$num1”. Now, let’s run the test cases:

$ ./unity_check.sh
Enter the input: 1
Number entered is 1

It works under a normal scenario. Let’s verify again for the blank input:

$ ./unity_check.sh
Enter the input:
./unity_check.sh: line 3: [: : integer expression expected
Not equal to One !!

Here we’re getting a different error, “integer expression expected”. Let’s debug the script:

$ bash -xv ./unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
+ read -p 'Enter the input: ' num1
Enter the input:
if [ "$num1" -eq 1 ]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi
+ '[' '' -eq 1 ']'
./unity_check.sh: line 3: [: : integer expression expected
+ echo 'Not equal to One !!'
Not equal to One !!

As we can see from the debug output, the if statement evaluates to:

if [ '' -eq 1 ]

And, we’re comparing apples with oranges! We were getting this error because we’re using the eq operator to compare the string value (”). We must note that the operator eq is intended for integer comparisons only. For the equality comparison of string values, we must use the “=” operator. Let’s modify our script and run the test cases:

$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if [ "$num1" = 1 ]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi
$ ./unity_check.sh
Enter the input: 3
Not equal to One !!
$ ./unity_check.sh
Enter the input: 1
Number entered is 1
$ ./unity_check.sh
Enter the input:
Not equal to One !!

It works as expected for all the test cases.

4. Using the Double Bracket Syntax to Prevent the Error

We can use the double bracket test construct [[ in Bash to evaluate the conditional expressions. Notably, this construct is not POSIX compliant and only available in Bash shell along with a few other shells. Hence, we can lose the portability of our scripts when moving to other Linux shell environments.

In the double bracket syntax, Bash doesn’t perform word splitting. This makes it more tolerant to cases where the variable might not be defined.

Let’s modify our script:

$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if [[ $num1 -eq 1 ]]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi

Now, let’s run our test case for blank input:

$ ./unity_check.sh
Enter the input:
Not equal to One !!

Great! It works as expected.

5. Handling the Variable Not Defined Cases

In the previous sections, we checked ways to prevent the “unary operator expected” errors. In this section, we’ll check ways to explicitly handle the variable not defined scenarios within our script.

5.1. Assigning Default Value to a Variable

We can assign a default value to a variable if it’s not defined:

$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if [ "${num:-1}" -eq 1 ]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi

Here, the ${num:-1} syntax ensures that the value of the num variable will be taken as 1 if it’s not defined. Additionally, let’s verify it by running some test cases:

$ ./unity_check.sh
Enter the input: 4
Not equal to One !!
$ ./unity_check.sh
Enter the input:
Number entered is 1

5.2. Using the -z Unary Operator

We can also test the empty string using the -z operator:

$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if [ -z "$num1" ]
then
    echo "The number is empty"
    exit 0
fi
if [ "${num1}" -eq 1 ]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi

Here, if the value of the variable is empty, we’re printing the relevant statement and exiting the script:

$ ./unity_check.sh
Enter the input:
The number is empty

6. Conclusion

In this tutorial, we looked at multiple techniques to address the“unary operator expected” error.

First, we discussed what’s causing this error. Then, we learned various solutions that can be utilized to prevent the issue.

Lastly, we checked a few approaches to explicitly handle the variable not defined cases in our shell scripts.