How to determine if a string is a substring of another in bash?
I want to see if a string is inside a portion of another string.
e.g.:
'ab' in 'abc' -> true
'ab' in 'bcd' -> false
How can I do this in a conditional of a bash script?
[[ "bcd" =~ "ab" ]]
[[ "abc" =~ "ab" ]]
the brackets are for the test, and as it is double brackets, it can so some extra tests like =~
.
So you could use this form something like
var1="ab"
var2="bcd"
if [[ "$var2" =~ "$var1" ]]; then
echo "pass"
else
echo "fail"
fi
Edit: corrected "=~", had flipped.
You can use the form ${VAR/subs}
where VAR
contains the bigger string and
subs
is the substring your are trying to find:
my_string=abc
substring=ab
if [ "${my_string/$substring}" = "$my_string" ] ; then
echo "${substring} is not in ${my_string}"
else
echo "${substring} was found in ${my_string}"
fi
This works because ${VAR/subs}
is equal to $VAR
but with the first occurrence of the string subs
removed, in particular if $VAR
does not contains the word subs
it won't be modified.
Using bash filename patterns (aka "glob" patterns)
substr=ab
[[ abc == *"$substr"* ]] && echo yes || echo no # yes
[[ bcd == *"$substr"* ]] && echo yes || echo no # no
The following two approaches will work on any POSIX-compatible environment, not just in bash:
substr=ab
for s in abc bcd; do
if case ${s} in *"${substr}"*) true;; *) false;; esac; then
printf %s\\n "'${s}' contains '${substr}'"
else
printf %s\\n "'${s}' does not contain '${substr}'"
fi
done
substr=ab
for s in abc bcd; do
if printf %s\\n "${s}" | grep -qF "${substr}"; then
printf %s\\n "'${s}' contains '${substr}'"
else
printf %s\\n "'${s}' does not contain '${substr}'"
fi
done
Both of the above output:
'abc' contains 'ab'
'bcd' does not contain 'ab'
The former has the advantage of not spawning a separate grep
process.
Note that I use printf %s\\n "${foo}"
instead of echo "${foo}"
because echo
might mangle ${foo}
if it contains backslashes.
shell case statement
This is the most portable solution, will work even on old Bourne shells and Korn shell
#!/bin/bash
case "abcd" in
*$1*) echo "It's a substring" ;;
*) echo "Not a substring" ;;
esac
Sample run:
$ ./case_substr.sh "ab"
It's a substring
$ ./case_substr.sh "whatever"
Not a substring
Note that you don't have to specifically use echo
you can use exit 1
and exit 0
to signify success or failure.
What we could do as well, is create a function (which can be used in large scripts if necessary) with specific return values ( 0 on match, 1 on no match):
$ ./substring_function.sh
ab is substring
$ cat substring_function.sh
#!/bin/sh
is_substring(){
case "$2" in
*$1*) return 0;;
*) return 1;;
esac
}
main(){
if is_substring "ab" "abcdefg"
then
echo "ab is substring"
fi
}
main $@
grep
$ grep -q 'ab' <<< "abcd" && echo "it's a substring" || echo "not a substring"
it's a substring
This particular approach is useful with if-else statements in bash
. Also mostly portable
AWK
$ awk '$0~/ab/{print "it is a substring"}' <<< "abcd"
it is a substring
Python
$ python -c 'import sys;sys.stdout.write("it is a substring") if "ab" in sys.stdin.read() else exit(1)' <<< "abcd"
it is a substring
Ruby
$ ruby -e ' puts "is substring" if ARGV[1].include? ARGV[0]' "ab" "abcdef"
is substring