Shell equality operators (=, ==, -eq)

Learn shell equality operators (=, ==, -eq) with practical examples, diagrams, and best practices. Covers bash, shell development techniques with visual explanations.

Understanding Shell Equality: =, ==, and -eq in Bash

A visual representation of three different comparison symbols: equals sign, double equals sign, and a mathematical equation symbol, illustrating the distinct uses of shell equality operators.

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.

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.

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.