Test if a string contains a substring
Use the =~
operator to make regular expression comparisons:
#!/bin/bash
file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file =~ $testseq ]];
then
echo "True"
else
echo "False"
fi
This way, it will compare if $file
has $testseq
on its contents.
user@host:~$ ./string.sh
False
If I change testseq="Const"
:
user@host:~$ ./string.sh
True
But, be careful with what you feed $testseq
with. If the string on it somehow represents a regex (like [0-9]
for example), there is a higher chance to trigger a "match".
Reference:
- Advanced Bash Script guide
You need to interpolate the $testseq
variable with one of the following ways:
$file == *_"$testseq"_*
(here$testseq
considered as a fixed string)$file == *_${testseq}_*
(here$testseq
considered as a pattern).
Or the _
immediately after the variable's name will be taken as part of the variable's name (it's a valid character in a variable name).
file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
case "$file" in
*_"$testseq"_*) echo 'True' ;;
*) echo 'False'
esac
Using case ... esac
is one of the simplest ways to perform a pattern match in a portable way. It works as a "switch" statement in other languages (bash
, zsh
, and ksh93
also allows you to do fall-through in various incompatible ways). The patterns used are the standard file name globbing patterns.
The issue you are having is due to the fact that _
is a valid character in a variable name. The shell will thus see *_$testseq_*
as "*_
followed by the value of the variable $testseq_
and an *
". The variable $testseq_
is undefined, so it will be expanded to an empty string, and you end up with *_*
, which obviously matches the $file
value that you have. You may expect to get True
as long as the filename in $file
contains at least one underscore.
To properly delimit the name of the variable, use "..."
around the expansion: *_"$testseq"_*
. This would use the value of the variable as a string. Would you want to use the value of the variable as a pattern, use *_${testseq}_*
instead.
Another quick fix is to include the underscores in the value of $testseq
:
testseq="_gen_"
and then just use *"$testseq"*
as the pattern (for a string comparison).