Reputation: 24767
How do I compare a variable to a string (and do something if they match)?
Upvotes: 1326
Views: 1746757
Reputation: 1812
Do you get "unexpected operator" when running a script as a cron job, but not from a console? If yes, your command interpreter is defaulting to dash. You can see it here.
$ which sh
/bin/sh
$ ls -l /bin/sh
/bin/sh -> dash*
Make sure you include the command interpreter
#!/bin/bash
at the top of your shell scripts if you want to use "=="
Just to weigh in on "=" vs "==", although they may both work if you have any coding background "=" should make you uncomfortable in a control statement as it tends to be an assignment operator rather than a test. Inconsistencies like this can make it difficult to shift between languages, and becomes even more painful to keep straight when you have Powershell using -eq for both numeric and string comparison. Bash always seemed backward with numeric evaluations using an operator consisting of a string (-eq) and string comparisons using a numeric operator "==" or "=" just you mess you up. If you ask me I'd say the problem is the distro swapping out bash. That is just my opinion, but this is my fix.
ln /bin/bash /bin/sh -sf
It's arguably not as fast, but has never broken anything.
Upvotes: 0
Reputation: 327
In addition to previous answers, you can also use case statement to compare strings once you have a predefined set of values to choose from.
For example, given that the user will provide an argument among these predefined values a
or b
or c
or default
once running the bash script, the following script demonstrates that.
#!/bin/bash
case "$1" in
a)
echo "create the file";;
b)
echo "edit the file";;
c)
echo "remove the file";;
*)
echo "read the file";;
esac
Where "$1"
is the argument provided by the user.
Upvotes: 2
Reputation: 115
I was struggling with the same situation for a while, here is how I could resolve:
if [ "$var1" == "$var2" ]; then
#dowhateveryouwant
fi
Be careful with the spaces left before and after the comparison sign, otherwise it won't work or it'll give you an unexpected result.
I've spent so much time on using a single equal(=) sign but didn't work. I Hope it can help.
Upvotes: 6
Reputation: 2194
Are you having comparison problems? (like below?)
var="true"
if [[ $var == "true" ]]; then
# It should be working, but it is not...
else
# It is falling here...
fi
Try like the =~ operator (regular expression operator) and it might work:
var="true"
if [[ $var =~ "true" ]];then
# Now it works here!!
else
# No more inequality
fi
Bash regex operator =~ (official reference)
StackOverflow further examples (here)
Upvotes: 3
Reputation: 3004
To compare strings with wildcards, use:
if [[ "$stringA" == *"$stringB"* ]]; then
# Do something here
else
# Do something here
fi
Upvotes: 80
Reputation: 31483
Or, if you don't need an else clause:
[ "$x" == "valid" ] && echo "x has the value 'valid'"
Upvotes: 189
Reputation: 343143
You can also use use case/esac:
case "$string" in
"$pattern" ) echo "found";;
esac
Upvotes: 25
Reputation: 1300
The following script reads from a file named "testonthis" line by line and then compares each line with a simple string, a string with special characters and a regular expression. If it doesn't match, then the script will print the line, otherwise not.
Space in Bash is so much important. So the following will work:
[ "$LINE" != "table_name" ]
But the following won't:
["$LINE" != "table_name"]
So please use as is:
cat testonthis | while read LINE
do
if [ "$LINE" != "table_name" ] && [ "$LINE" != "--------------------------------" ] && [[ "$LINE" =~ [^[:space:]] ]] && [[ "$LINE" != SQL* ]]; then
echo $LINE
fi
done
Upvotes: 34
Reputation: 1001
I did it in this way that is compatible with Bash and Dash (sh):
testOutput="my test"
pattern="my"
case $testOutput in (*"$pattern"*)
echo "if there is a match"
exit 1
;;
(*)
! echo there is no coincidence!
;;esac
Upvotes: 1
Reputation: 7347
Bash 4+ examples. Note: not using quotes will cause issues when words contain spaces, etc. Always quote in Bash, IMO.
Here are some examples in Bash 4+:
Example 1, check for 'yes' in string (case insensitive):
if [[ "${str,,}" == *"yes"* ]] ;then
Example 2, check for 'yes' in string (case insensitive):
if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then
Example 3, check for 'yes' in string (case sensitive):
if [[ "${str}" == *"yes"* ]] ;then
Example 4, check for 'yes' in string (case sensitive):
if [[ "${str}" =~ "yes" ]] ;then
Example 5, exact match (case sensitive):
if [[ "${str}" == "yes" ]] ;then
Example 6, exact match (case insensitive):
if [[ "${str,,}" == "yes" ]] ;then
Example 7, exact match:
if [ "$a" = "$b" ] ;then
Enjoy.
Upvotes: 21
Reputation: 311755
if [ "$x" = "valid" ]; then
echo "x has the value 'valid'"
fi
If you want to do something when they don't match, replace =
with !=
. You can read more about string operations and arithmetic operations in their respective documentation.
$x
?You want the quotes around $x
, because if it is empty, your Bash script encounters a syntax error as seen below:
if [ = "valid" ]; then
==
operatorNote that Bash allows ==
to be used for equality with [
, but this is not standard.
Use either the first case wherein the quotes around $x
are optional:
if [[ "$x" == "valid" ]]; then
or use the second case:
if [ "$x" = "valid" ]; then
Upvotes: 1850
Reputation: 3595
I have to disagree one of the comments in one point:
[ "$x" == "valid" ] && echo "valid" || echo "invalid"
It's just it looks like one to, hmm, the uninitiated...
It uses common patterns as a language, in a way;
And after you learned the language.
It is a simple logical expression, with one special part: lazy evaluation of the logic operators.
[ "$x" == "valid" ] && echo "valid" || echo "invalid"
Each part is a logical expression; the first may be true or false, the other two are always true.
(
[ "$x" == "valid" ]
&&
echo "valid"
)
||
echo "invalid"
Now, when it is evaluated, the first is checked. If it is false, than the second operand of the logic and &&
after it is not relevant. The first is not true, so it can not be the first and the second be true, anyway.
Now, in this case is the the first side of the logic or ||
false, but it could be true if the other side - the third part - is true.
So the third part will be evaluated - mainly writing the message as a side effect. (It has the result 0
for true, which we do not use here)
The other cases are similar, but simpler - and - I promise! are - can be - easy to read!
(I don't have one, but I think being a UNIX veteran with grey beard helps a lot with this.)
Upvotes: 48
Reputation: 2857
a="abc"
b="def"
# Equality Comparison
if [ "$a" == "$b" ]; then
echo "Strings match"
else
echo "Strings don't match"
fi
# Lexicographic (greater than, less than) comparison.
if [ "$a" \< "$b" ]; then
echo "$a is lexicographically smaller then $b"
elif [ "$a" \> "$b" ]; then
echo "$b is lexicographically smaller than $a"
else
echo "Strings are equal"
fi
Notes:
if
and [
and ]
are important>
and <
are redirection operators so escape it with \>
and \<
respectively for strings.Upvotes: 131
Reputation: 880
I would probably use regexp matches if the input has only a few valid entries. E.g. only the "start" and "stop" are valid actions.
if [[ "${ACTION,,}" =~ ^(start|stop)$ ]]; then
echo "valid action"
fi
Note that I lowercase the variable $ACTION
by using the double comma's. Also note that this won't work on too aged bash versions out there.
Upvotes: 12