How to compare strings in Bash

Learn how to compare strings in bash with practical examples, diagrams, and best practices. Covers string, bash development techniques with visual explanations.

Mastering String Comparisons in Bash: A Comprehensive Guide

Hero image for How to compare strings in Bash

Learn the various methods for comparing strings in Bash, including equality, inequality, pattern matching, and best practices for robust scripting.

String comparison is a fundamental operation in any programming language, and Bash is no exception. Whether you're validating user input, controlling script flow based on variable values, or performing conditional checks, understanding how to correctly compare strings is crucial for writing effective and error-free shell scripts. This guide will walk you through the different operators and constructs available in Bash for string comparison, from basic equality checks to more advanced pattern matching.

Basic String Equality and Inequality

The most common string comparisons involve checking if two strings are identical or different. Bash provides specific operators within conditional expressions ([[ ... ]] or [ ... ]) to perform these checks. While [ ... ] is a POSIX standard, [[ ... ]] is a Bash-specific extension that offers more features and is generally preferred for its robustness and reduced word splitting issues.

# Using == for equality (preferred with [[ ]])
string1="hello"
string2="world"
string3="hello"

if [[ "$string1" == "$string3" ]]; then
    echo "String1 and String3 are equal."
else
    echo "String1 and String3 are not equal."
fi

# Using != for inequality
if [[ "$string1" != "$string2" ]]; then
    echo "String1 and String2 are not equal."
else
    echo "String1 and String2 are equal."
fi

# Using = for equality (with [ ])
# Note: = is also used for assignment, so == is clearer for comparison
if [ "$string1" = "$string3" ]; then
    echo "String1 and String3 are equal (using =)."
fi

Examples of basic string equality and inequality checks

Lexicographical Comparison (Alphabetical Order)

Beyond simple equality, you might need to determine if one string comes before or after another in alphabetical (lexicographical) order. Bash provides operators for this as well, primarily within the [[ ... ]] construct.

str_a="apple"
str_b="banana"
str_c="Apple"

# Using < for 'less than' (comes before alphabetically)
if [[ "$str_a" < "$str_b" ]]; then
    echo "'$str_a' comes before '$str_b'."
fi

# Using > for 'greater than' (comes after alphabetically)
if [[ "$str_b" > "$str_a" ]]; then
    echo "'$str_b' comes after '$str_a'."
fi

# Case sensitivity matters!
if [[ "$str_a" < "$str_c" ]]; then
    echo "'$str_a' comes before '$str_c' (due to case)."
else
    echo "'$str_a' does NOT come before '$str_c' (due to case)."
fi

Lexicographical string comparison examples

Pattern Matching with == and !=

One of the powerful features of [[ ... ]] is its ability to perform pattern matching using the == and != operators. Unlike regular expressions, these use shell globbing patterns (wildcards) similar to those used for filename expansion. This allows for flexible checks without needing external tools like grep.

filename="document.txt"
user_input="yes"

# Check if filename ends with .txt
if [[ "$filename" == *.txt ]]; then
    echo "'$filename' is a text file."
fi

# Check if user input starts with 'y' or 'Y'
if [[ "$user_input" == [yY]* ]]; then
    echo "User confirmed."
fi

# Check if string contains digits
if [[ "some_string123" == *[0-9]* ]]; then
    echo "String contains digits."
fi

# Check if string does NOT match a pattern
if [[ "$filename" != *.log ]]; then
    echo "'$filename' is not a log file."
fi

Examples of pattern matching with glob wildcards

flowchart TD
    A[Start]
    B{Compare String1 and String2}
    C{Equality (== or =)}
    D{Inequality (!=)}
    E{Lexicographical (< or >)}
    F{Pattern Match (== with wildcards)}
    G[Result: Equal]
    H[Result: Not Equal]
    I[Result: String1 < String2]
    J[Result: String1 > String2]
    K[Result: Pattern Matched]
    L[Result: Pattern Not Matched]

    A --> B
    B --> C
    B --> D
    B --> E
    B --> F

    C --> G
    C --> H
    D --> G
    D --> H
    E --> I
    E --> J
    F --> K
    F --> L

Decision flow for Bash string comparison methods