bash, dash and string comparison
-
11-09-2019 - |
Question
I am trying to compare two strings in a simple shell script.
I was using /bin/sh
instead of /bin/bash
, and after countless hours of debugging, it turns out sh (which is actually dash) can't handle this block of code:
if [ "$var" == "string" ]
then
do something
fi
What is a portable way to compare strings using /bin/sh
? I know I can always do the opposite by using !=, but I am wondering about a cleaner, portable way.
Solution
dash
is a very strict POSIX shell, if it work in dash
it is almost certain it would work in other POSIX shell.
Try:
if [ "$var" = "string" ]
then
some_command
fi
OTHER TIPS
Why is there even a possibility that your script will be run by the "wrong" shell? I would think you could make that a pre-requisite of your product by using the standard sh-bang line at the top of your script:
#!/bin/bash
Even if a user uses a different shell, the other shells are generally still there and, if not, simply complain and state that they are a pre-req.
Exactly the same way that a specific kernel level, or the existence of awk, can be a pre-req.
For your specific question, I believe both sh
and bash
allow the single '=' to be used for string comparisons - that is POSIX behavior:
if [ "a" = "a" ] ; then
echo yes
fi
yes
Use =
instead of ==
. Comparisons are handled by test(1). /usr/bin/[
is typically a link to /usr/bin/test
. The only difference is that if you use [
in a shell script, the ]
is required as well.
Note that bash has a built-in test
/[
, so it doesn't actually use /usr/bin/test
.
The answers already posted are certainly correct, but it may be worthwhile to note that occasionally parameter expansion can serve the same purpose with perhaps some additional flexibility.
% p() { printf 'notvar = %b\n' "${notvar##"${string1}"}${string2}" ; }
% string1='some stuff about things\c'
% string2='some different stuff maybe'
% notvar="$string1" p
> 'some different stuff maybe'
% notvar="$string2" p
> 'some stuff about things'
Ok, so the above isn't super-useful as is, but also consider that you can use the similar methods for testing variables in here-documents, in-line variable assignments if necessary (to a degree...), or even just as a shorter (and faster!) means of writing your first statement.
[ ! "${var##"string"}" ] && _MATCH || _NOMATCH
Or even...
[ ${#var#*"${s=string}"} -lt ${#var} ] && _SUB_STRING_TEST=TRUE
Possibly even...
% p() { printf '%s is %s of %s' "$2" "${var_chk-not}" "$1"
> }<<HEREDOC
> ${in="${1##*"${2}"*}"}
> ${in:-
> ${in="${1##"${2}"}"}
> ${in:-${var_chk=all}
> ${var_chk=some}
> }
> HEREDOC
%
you can use awk
awk 'BEGIN{
string1="test"
string2="tes1t"
if(s1==s2){
print "same string"
}else{
print "not same"
}
}'