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.