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?
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It only takes a minute to sign up.
Sign up to join this communityI 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.
[[ $string =~ $substring ]]
. I updated the answer.
May 25, 2013 at 0:38
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.
xrandr
monitor names stored in variable. +1 and welcome to 1K rep club :)
Feb 10, 2018 at 16:31
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 -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 '$0~/ab/{print "it is a substring"}' <<< "abcd"
it is a substring
$ 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 -e ' puts "is substring" if ARGV[1].include? ARGV[0]' "ab" "abcdef"
is substring
Mind the [[
and "
:
[[ $a == z* ]] # True if $a starts with an "z" (pattern matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
[ $a == z* ] # File globbing and word splitting take place.
[ "$a" == "z*" ] # True if $a is equal to z* (literal matching).
So as @glenn_jackman said, but mind that if you wrap the whole second term in double quotes, it will switch the test to literal matching.
Similar to edwin's answer, but with improved portability for posix & ksh, and a touch less noisy than Richard's:
substring=ab
string=abc
if [ "$string" != "${string%$substring*}" ]; then
echo "$substring IS in $string"
else
echo "$substring is NOT in $string"
fi
string=bcd
if [ "$string" != "${string%$substring*}" ]; then
echo "$string contains $substring"
else
echo "$string does NOT contain $substring"
fi
Output:
abc contains ab
bcd does NOT contain ab