Shell equality operators (=, ==, -eq)
Categories:
Understanding Shell Equality: =, ==, and -eq in Bash

Explore the nuances of shell equality operators in Bash: =, == for string comparison, and -eq for numerical comparison. Learn when and how to use each to avoid common scripting pitfalls.
In shell scripting, particularly in Bash, comparing values is a fundamental operation. However, the choice of equality operator can significantly impact the outcome of your scripts. Unlike many programming languages where a single operator might handle both string and numeric comparisons, Bash distinguishes between them. This article delves into the specifics of =, ==, and -eq, explaining their proper usage and common pitfalls.
String Comparison: = and ==
Both = and == are used for string comparison in Bash. Historically, = was the standard, but == is now widely accepted and often preferred for clarity, especially for those coming from other programming languages. Within [[ ... ]] (the new test construct), == offers pattern matching capabilities, which = does not. However, within [ ... ] (the old test construct), both behave identically as simple string equality checks.
STRING1="hello"
STRING2="world"
STRING3="hello"
# Using [ ... ]
if [ "$STRING1" = "$STRING3" ]; then
echo "[ = ]: STRING1 equals STRING3"
fi
if [ "$STRING1" == "$STRING3" ]; then
echo "[ == ]: STRING1 equals STRING3"
fi
if [ "$STRING1" = "$STRING2" ]; then
echo "[ = ]: This will not print"
else
echo "[ = ]: STRING1 does not equal STRING2"
fi
# Using [[ ... ]]
if [[ "$STRING1" == "$STRING3" ]]; then
echo "[[ == ]]: STRING1 equals STRING3"
fi
# Pattern matching with [[ == ]]
PATTERN="h*o"
if [[ "$STRING1" == $PATTERN ]]; then
echo "[[ == ]]: STRING1 matches pattern '$PATTERN'"
fi
Examples of string comparison using = and == in Bash.
"$VAR"). This prevents issues if the variable is empty or contains spaces, which could lead to syntax errors or unexpected behavior.Numerical Comparison: -eq
For comparing numerical values, Bash provides a distinct set of operators, with -eq being the equality operator. Using = or == for numbers will perform string comparison, which can lead to incorrect results (e.g., "10" == "2" is false, but "10" > "2" is true lexicographically, while numerically 10 > 2 is true). Always use -eq for integer comparisons.
NUM1=10
NUM2=20
NUM3=10
# Correct numerical comparison
if [ "$NUM1" -eq "$NUM3" ]; then
echo "-eq: NUM1 equals NUM3"
fi
if [ "$NUM1" -eq "$NUM2" ]; then
echo "-eq: This will not print"
else
echo "-eq: NUM1 does not equal NUM2"
fi
# Incorrect string comparison of numbers
if [ "$NUM1" = "$NUM3" ]; then
echo "= : NUM1 equals NUM3 (as strings)"
fi
if [ "$NUM1" = "$NUM2" ]; then
echo "= : This will not print (as strings)"
else
echo "= : NUM1 does not equal NUM2 (as strings)"
fi
# Example of potential pitfall with string comparison on numbers
VAR_A=10
VAR_B=2
if [ "$VAR_A" \> "$VAR_B" ]; then
echo "String comparison: '$VAR_A' is lexicographically greater than '$VAR_B' (incorrect for numbers)"
else
echo "String comparison: '$VAR_A' is NOT lexicographically greater than '$VAR_B'"
fi
if [ "$VAR_A" -gt "$VAR_B" ]; then
echo "Numerical comparison: '$VAR_A' is numerically greater than '$VAR_B' (correct)"
fi
Demonstrating numerical comparison with -eq and the dangers of using string operators for numbers.
-eq and related numerical operators (-ne, -gt, -ge, -lt, -le) only work with integers. For floating-point number comparisons, you'll need to use external tools like bc or awk.Choosing the Right Operator: A Decision Flow
To summarize, the choice between string and numerical comparison operators depends entirely on the data type you are comparing. Using the wrong operator is a common source of bugs in shell scripts. The following diagram illustrates the decision process for selecting the appropriate equality operator.
flowchart TD
A[Start: Need to compare two values?] --> B{Are values strictly numbers?};
B -- Yes --> C{Compare using numerical operators};
C --> D["-eq" for equality, "-ne" for inequality, etc.];
B -- No --> E{Are values strings or mixed types?};
E --> F{Compare using string operators};
F --> G["=" or "==" for equality, "!=" for inequality];
D --> H[End];
G --> H[End];Decision flow for choosing between string and numerical equality operators in Bash.
[[ ... ]] is generally more robust and feature-rich than [ ... ], both are valid. For simple equality checks, [ ... ] is perfectly fine. However, for pattern matching or more complex conditions, [[ ... ]] is the way to go.