At first glance, comparing strings in bash might appear to be a niche use-case scenario. But as I’ll explain below, it’s one of the most common operations you’ll be doing as a Linux command-line user. You can compare these strings in bash as standalone instructions on the command line or by entering these instructions into an executable file.
So without further ado, let’s start with all the different ways you can compare strings in bash. This list doesn’t include comparisons for 3rd party tools like “awk”, and I’ve combined a few methods that I think are too similar to each other to merit being called a separate technique.
Comparing Strings in Bash – All the Techniques
Here’s a breakdown of the ten ways to compare strings in bash.
1. Equality and Inequality Operators
The most basic way to compare two strings in bash is to check whether or not they’re the same. We do this using double equal signs (==) for equality and the familiar “not equal” operator combination (!=).
Here are examples of each:
if [ "$var1" == "$var2" ]; then echo "Equal"; fi if [ "$var1" != "$var2" ]; then echo "Not equal"; fi
In the above code block, I’m comparing two variables $var1 and $var2. In the first example, I’m checking to see if they’re equal, and in the second, I’m checking if they’re unequal, and the response will vary depending on the condition.
The equality and inequality operators are the easiest to understand, and the ones you’ll be using a lot in bash scripts when checking permissions or roles.
2. Numerical Comparison
It’s strange, but true, that variables in bash are typically stored and treated as strings, even when the values are numbers. Think of an Excel sheet cell containing a number that doesn’t behave like one. For example, if you perform a sorting operation on such a variable, it’ll sort in order of how it appears in the dictionary, rather than whether or not the number is greater or lesser.
So if you have two numbers in bash, stored in variables, and you want to check which one is greater than the other, you have to use something called a “numerical comparison”, which is very different from what you’re used to in other languages which treat variables differently depending on how they’re declared.
For numerical comparisons, bash has the following operators:
- eq – equality
- lt – inequality
- le – lesser than or equal
- gt – greater than
- ge – greater than or equal
- ne – not equal
For example, here’s a simple example of using the “lesser than” operator:
a="10" b="20" if [ "$a" -lt "$b" ]; then echo "$a is less than $b" fi
In this example, the two variables $a and $b are numbers. However, they’re represented by strings internally, so when we want to check if one is lesser than the other, we use the “lt” numerical operator.
While technically, the “eq” can also be performed using an equality (==) operator, the outcome might be unexpected if there are things like leading zeros. For example:
In the above example, I’ve created two variables with the values “1” and “001”. While they are numerically the same, they are different strings. So when I use the equality comparison operator, bash tells me that they’re not the same. If, however, I use the “-eq” operator, bash correctly recognizes that I’m trying to compare them numerically and gives me the right answer.
To use the numerical operators, you must precede them with a dash (-) as shown in the examples above. Granted, they’re not as intuitive to write as regular comparison operators in other languages. However, because bash treats all variables as strings, we have no choice but to use these slightly unintuitive operators for numerical comparisons.
3. Partial String Matching
While the equality and inequality signs allow you to detect identical matches of a string to others, we often need to partially match strings and substrings, and we can compare them in bash in a few ways.
For example, consider the following code:
if [[ "$str" == *"pattern"* ]]; then echo "str contains pattern"; fi
In the above example, I’m trying to see if the string “pattern” is within the $str variable. I do this by including the asterisk (*) wildcard before and after the pattern. The asterisk indicates any sequence of characters. Putting an asterisk before and after a pattern indicates that I want to match any string that has “pattern” in it. The above technique can also be used to check if one string is a substring of the other.
The second kind of wildcard for string comparisons in bash is the question mark (?). This matches any single character, compared to the asterisk, which can match any range of characters. So the following code:
str="abc1def" if [[ "$str" == abc?def ]]; then echo "String matches the pattern 'abc?def'" fi
Will match any string that starts with “abc” and ends with “def” with any character in-between. So while the above example matches abc1def, it can also match abc2def.
Finally, the third kind of wildcard is one that can match a range of characters within square brackets. For example:
str="Apple" if [[ "$str" == [Aa]pple ]]; then echo "String starts with 'A' or 'a', followed by 'pple'" fi
In the above example, the square brackets [Aa] will match either “A” or “a”. You can also use ranges like [a-z] to match any character from a to z.
Usage of double square brackets
Note that in each of the above examples, the string matching happens between double square brackets [[ ]]. That’s because partial string comparisons aren’t possible if you use ordinary conditional square brackets. This makes particular sense, in the third case of partial string matching, since the range square brackets [ ] would conflict with the conditional ones.
4. Regex String Comparisons
Bash allows you to compare strings to regular expressions. Take the following code, for example:
if [[ "$str" =~ ^[a-zA-Z]+$ ]]; then echo "str is alphabetic"; fi
In the above example, I’m matching “$str” with a regular expression that checks to see if the string is alphabetic. This isn’t the place to go into the details of how regular expressions work, however – that’s a separate article entirely!
Note that instead of a standalone equal sign, we use the combination =~ to tell bash that what follows is a regular expression. And since regexes can use square brackets for their expressions, the matching requires that you utilize double square brackets [[ ]] for partial string matching.
5. String Length Comparisons
Instead of comparing the contents of two strings, you can, instead, compare their length using the hash (#) operator and compare lengths using the numerical comparison we say in the second method. For example:
if [ "${#str1}" -gt "${#str2}" ]; then echo "str1 is longer"; fi
Here, we extract the length of str1 into a string itself via “${#str1}” and use the “-gt” numerical comparison operator to see if str1 is longer than str2. Of course, you can use any of the numerical operators, not just gt.
Conclusion
As you can see, there are multiple ways to compare strings to each other in bash. Truth be told, bash isn’t the most well-formed programming language – just look at how it treats all variables as strings! But using the above operators, you can compare strings in many different ways, from using simple equal signs, all the way to regexes. This article should help you choose the right tool for the job, and I hope you found it useful!
I’m a NameHero team member, and an expert on WordPress and web hosting. I’ve been in this industry since 2008. I’ve also developed apps on Android and have written extensive tutorials on managing Linux servers. You can contact me on my website WP-Tweaks.com!
Leave a Reply