It is a normal or I would say daily use case for a Linux developer to work on a script which requires comparison of strings. But I have seen many people tend to get confused between strings and integers. So before we go ahead and learn about string comparison in bash, let us understand the basic different between bash and integer value.
Difference between Integers and Strings
Now in bash we have strings and integers. So any text provided under single quotes ('') or double quotes ("") is considered as string. So even if you provide a numerical value under single or double quotes which by default should be an integer but due to the quotes it will be considered as string.
Let us take some examples to understand the difference between string and integer in bash:
For examples:
VAL="text" => Here text is a string VAL="10" => Here 10 is a string even though this is an integer as it is provided with double quotes VAL='11' => Again for the same reason 11 will be considered as string as it is under single quotes VAL=11 => Here 11 is integer so this needs separate handling for bash string comparison
Comparison operators for strings
First let us understand the different comparison operator available for sting comparison in bash and shell script.
Name | Operator syntax | Syntax with single bracket | Syntax with double brackets | Comment |
---|---|---|---|---|
is equal to | = (or) == |
[ "string1" = "string2" ] |
[[ "$string1" == "string2" ]] |
Returns TRUE if both the operands are equal |
is not equal to | != |
[ "string1" != "string2" ] |
[[ "string1" != "string2" ]] |
Returns TRUE if both the operands are NOT equal |
is less than | < |
[ "string1" \< "string2" ] |
[[ "string1" < "string2" ]] |
Use escape character for the operator in single bracket Returns TRUE if the right operand is considered lower than the left operand The comparison is done using ASCII alphabetical order |
is greater than | > |
[ "string1" \> "string2" ] |
[[ "string1" < "string2" ]] |
Use escape character for the operator in single bracket Returns TRUE if the right operand is considered higher than the left operand The comparison is done using ASCII alphabetical order |
zero string length | -z |
[ -z "string2" ] |
[[ -z "string2" ]] |
Returns TRUE if the provided String has zero length i.e. null value |
non zero length | -n |
[ -n "string2" ] |
[[ -n "string2" ]] |
It is IMPORTANT that the string is under inverted commas Returns TRUE if string is non-zero i.e. not null |
Check if Strings are Equal
Bash compares strings by length and each character match. For example in this shell script I have defined both variables with same string
VAR1="golinuxcloud"
VAR2="golinuxcloud"
if [[ "$VAR1" == "$VAR2" ]];then
echo "exit status: $?"
echo "$VAR1 is equal to $VAR2"
else
echo "exit status: $?"
echo "$VAR1 is NOT equal to $VAR2"
fi
The output from this script shows that the first condition returns TRUE with exit status as zero so both strings are considered EQUAL
exit status: 0 golinuxcloud is equal to golinuxcloud
If we run this in DEBUG mode (the best thing I like about shell scripts)
+ VAR1=golinuxcloud + VAR2=golinuxcloud + [[ golinuxcloud == \g\o\l\i\n\u\x\c\l\o\u\d ]] + echo 'exit status: 0' exit status: 0 + echo 'golinuxcloud is equal to golinuxcloud' golinuxcloud is equal to golinuxcloud
As you see, bash is comparing both the string's length and each character before returning TRUE status
Check if Strings are NOT Equal
We will make some change in one of our variables and then perform the string comparison
VAR1="golinuxcloud"
VAR2="website"
if [[ "$VAR1" != "$VAR2" ]];then
echo "exit status: $?"
echo "$VAR1 is NOT equal to $VAR2"
fi
The output of this script shows the first condition returns TRUE with exit status as zero so both strings are not equal
exit status: 0 golinuxcloud is NOT equal to website
Compare strings using ASCII order
I have personally not used this in my career till now, I would be interested to know if any my readers have any use case to use such comparison for strings
I have taken two variables with two different strings
VAR1="A" VAR2="B" if [[ "$VAR1" > "$VAR2" ]];then echo "exit status: $?" echo "$VAR1 is greater than $VAR2" elif [[ "$VAR1" == "$VAR2" ]];then echo "exit status: $?" echo "$VAR1 is equal to $VAR2" else echo "exit status: $?" echo "$VAR1 is lesser than $VAR2" fi
The output of this script would be
exit status: 1 A is lesser than B
Because as per ASCII code Letter A has ASCII code of 065
while Letter B has 066
so Letter A is considered lesser than B
Check if string is empty
This is one of the most used operator in real time production environment where we are collecting output from some command into a variable and want to make sure that the variable is not empty i.e. it was able to collect the command output
In this script I am trying to get PID of a dummy process so it is expected that the variable will be empty
VAR=`pidof dummy`
if [ -z "$VAR" ]; then
echo "exit status: $?"
echo "\$VAR is null."
else
echo "exit status: $?"
echo "\$VAR is NOT null."
echo "value: $VAR"
fi
Output from this script confirms that our string is empty and returns TRUE
exit status: 0 $VAR is null.
In this script I will look for PID of java process
VAR=`pidof java`
if [ -z "$VAR" ]; then
echo "exit status: $?"
echo "\$VAR is null."
else
echo "exit status: $?"
echo "\$VAR is NOT null."
echo "value: $VAR"
fi
Output from this script tells us that the VAR string is not empty and returns FALSE
exit status: 1 $VAR is NOT null. value: 10592
Check if string is non-zero or not-null
We can use the same script to verify if the variable is non-zero.
The difference is with -z
we get zero exit when string has no value while the just opposite with -n
which will return zero exit status if the string is non-zero
VAR=`pidof java`
if [ -n "$VAR" ]; then
echo "exit status: $?"
echo "\$VAR is NOT null."
else
echo "exit status: $?"
echo "\$VAR is null."
echo "value: $VAR"
fi
The output from the script
exit status: 0 $VAR is NOT null.
Shell Script: string comparison operator examples
We will check some examples to understand and learn bash string comparison.
Here I have created a single script which will use all the bash string comparison operators we learned about in a while loop so that I don't have to write separate function to demonstrate an example. This loop will continue to run unless I manually send an interrupt signal to the script:
# cat /tmp/bash_compare_strings.sh #!/bin/bash # Bash Compare Strings # Run the script untill manually interrupted while true; do # Collect VAR1 and VAR2 value from end user read -r -p "Enter VAR1 value: " VAR1 read -r -p "Enter VAR1 value: " VAR2 # Check if $VAR1 value is less that $VAR2 if [[ "$VAR1" < "$VAR2" ]];then echo "$VAR1 is less than $VAR2" # Check if $VAR1 value is greater than $VAR2 elif [[ "$VAR1" > "$VAR2" ]];then echo "$VAR1 is greater than $VAR2" # Check if $VAR1 is equal to $VAR2 elif [[ "$VAR1" == "$VAR2" ]];then echo "$VAR1 is equal to $VAR2" # Chcek if $VAR1 is not equal to $VAR2 elif [[ "$VAR1" != "$VAR2" ]];then echo "$VAR1 is NOT equal to $VAR2" else # If none of the above condition matches echo "Unable to get the status" fi done
Now we will give different values to VAR1 and VAR2 in this script and check the exit status. If you observe I have placed both variables under double quotation mark so even if you give numbers as an input to this script, they will be considered as strings.
Provide executable permission to the script
# chmod u+x /tmp/bash_compare_strings.sh
Let us execute our script to learn more about bash compare strings operator:
# /tmp/bash_compare_strings.sh Enter VAR1 value: deepak Enter VAR1 value: deepak deepak is equal to deepak <- We know both the strings are same Enter VAR1 value: deepak Enter VAR1 value: amit deepak is greater than amit <- deepak has more number of char compared to amit Enter VAR1 value: amit Enter VAR1 value: deepak amit is less than deepak <- amit has less number of char compared to deepak Enter VAR1 value: 100 Enter VAR1 value: 100 100 is equal to 100 <- both the strings are same Enter VAR1 value: deep100 Enter VAR1 value: deep101 deep100 is less than deep101 <- we have combined text with number. deep is same in both variables but 100 is less than 101 Enter VAR1 value: deep100 Enter VAR1 value: amit101 deep100 is greater than amit101 <- This depends on the combination of ASCII code value
Perform regex and pattern (=~) match for strings
We will check some more examples to compare bash regex match and bash pattern match. Here I have written a one liner shell script to check for bash regex match and bash pattern match.
[root@controller ~]# [[ "my name is deepak prasad" =~ "prasad"$ ]] && echo "bash regex match" || echo "bash regex nomatch" bash regex match
We can also break this into multi line script which will be easier to understand for new comers
if [[ "my name is deepak prasad" =~ "prasad"$ ]]; then echo "bash regex match" else echo "bash regex nomatch" fi
Here we use =~
instead of ==
to match a pattern and dollar $
sign to match the last word of the string. Now since "prasad
" is the last word in my name is deepak prasad
hence the bash pattern match is successful.
Similarly I check the for starting word using ^
in my string, now since my
is the starting word in my name is deepak prasad
the bash pattern match is successful.
[root@controller ~]# [[ "my name is deepak prasad" =~ ^"my" ]] && echo "bash regex match" || echo "bash regex nomatch" bash regex match
We can also look out for certain word within a string without any regex as shown below. Since deepak
word is present in my name is deepak prasad
, the bash pattern match is successful
[root@controller ~]# [[ "my name is deepak prasad" =~ "deepak" ]] && echo "bash regex match" || echo "bash regex nomatch" bash regex match
By default if we use "is equal to
" for the below check then it says "nomatch
" as with ==
the shell will try to match character to character for both the variables due to which the check fails
[root@controller ~]# [[ "my name is deepak prasad" == "deepak" ]] && echo "bash regex match" || echo "bash regex nomatch" bash regex nomatch
So we use wildcard (*
) regex to match the string to ignore starting and ending text, the bash regex match is successful.
[root@controller ~]# [[ "my name is deepak prasad" == *"deepak"* ]] && echo "bash regex match" || echo "bash regex nomatch" bash regex match
Conclusion
Bash is still one of the most used programming language across industry although it is being taken over by Python, Go and other languages which serve more advantage but I still feel it your script contains more of system commands then bash is still the preferred language for Administrators and Developers. In this tutorial guide we learned about different string comparison operators, performing regex and pattern match for strings using different examples.
Lastly I hope the steps from the article to perform string comparison in shell scripts on Linux was helpful. So, let me know your suggestions and feedback using the comment section.
References
I have used below external references for this tutorial guide
Comparison Operators
ASCII Binary Character Table