How to compare strings in Bash
Categories:
Mastering String Comparisons in Bash: A Comprehensive Guide

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
"$my_var"
). This prevents issues with word splitting and globbing, especially if the variable contains spaces or special characters. While [[ ... ]]
is more forgiving, quoting is still a good practice.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
<
or >
for lexicographical comparison within [ ... ]
, you must escape them (e.g., \<
, \>
) because they are redirection operators in the shell. This is another reason why [[ ... ]]
is often preferred, as it handles these operators without requiring escaping.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
=~
operator within [[ ... ]]
. This allows for powerful and flexible string validation and extraction, but it's beyond the scope of basic string comparison covered here.