98

I have a string ${testmystring} in my .sh script and I want to check if this string does not contain another string.

    if [[ ${testmystring} doesNotContain *"c0"* ]];then
        # testmystring does not contain c0
    fi 

How can I do that, i.e. what is doesNotContain supposed to be?

Jahid
  • 21,542
  • 10
  • 90
  • 108
machinery
  • 5,972
  • 12
  • 67
  • 118

3 Answers3

166

Use !=.

if [[ ${testmystring} != *"c0"* ]];then
    # testmystring does not contain c0
fi

See help [[ for more information.

cychoi
  • 2,890
  • 3
  • 22
  • 31
  • 2
    The `{ }` and the quotes around `c0` are superfluous. – cdarke May 31 '15 at 12:57
  • 11
    I agree they're superfluous for the mere example shown above. But if the variable name and the pattern string are getting more complex (e.g.: containing space in the pattern string), quoting them is necessary. Anyway, quoting them usually does no harm. :) – cychoi May 31 '15 at 13:02
  • 2
    True it does no harm, and if you enjoy typing them then knock yourself out! Sorry, I know this is pedantic, its just that I find people often use things like `{ }` by rote without understanding when they are needed and when they are not (I did upvote you). – cdarke May 31 '15 at 13:06
  • @cdarke: as far as i know not using {} incurs in a performance penalty because the shell cannot immediately assume it is a variable while with it, it can. I am not completely absolutely sure and worse i cant remember where I saw the numbers. – Paulo Neves Apr 13 '17 at 07:18
  • @PauloNeves: wow! I would love to see the benchmark for that, and the source. I can see that might be the case for `csh` where the `{ }` are needed in quite a few scenarios. Please let me know where you got this from, meanwhile I'm going to check the bash source code. – cdarke Apr 13 '17 at 08:23
  • @chepner: can you look at the last few comments and give your opinion please? – cdarke Apr 13 '17 at 08:24
  • @PauloNeves: looking at `subst.c`, function `extract_dollar_brace_string`, it looks to me like there is more processing with the braces, not less. However the difference in performance without the braces would be trivial. I am prepared to be proven wrong! – cdarke Apr 13 '17 at 08:46
  • The quotes around the right side regex could actually cause some issues in bash >= 3.2. See comment here, https://stackoverflow.com/questions/229551/string-contains-in-bash#comment48465862_231298 and E14 http://tiswww.case.edu/php/chet/bash/FAQ as per the comment. – dragon788 Jul 10 '17 at 19:17
  • @ITguy Which command is not found? Are you using the latest version of Bash? – cychoi Jan 08 '18 at 15:44
  • @cdarke, the reason to always use brackets and quotes is to develop good programming practices. While in some cases it is superfluous and not required, it doesn't really hurt, and if you've developed it as a habit, you always do it without any extra effort. This will reduce the amount of debugging required, which can get to be extensive with large programs of hundreds and even thousands of lines of code. In effect, developing the habit of always doing so saves time in the long run. It's best to develop good programming practices early. Take it from an old programmer from way back. – Randyman99 Mar 08 '19 at 00:15
  • 2
    @Randyman99: while I agree with your aim, I don't believe that adding superfluous characters when you don't understand what they do develops good programming practice. That's my point - too many people use them because of a cargo culture and they never learn what they are actually for - that's not good programming practice. Defensive programming is good, mindless programming is not good. Take that from someone who has been programming professionally for fifty years. – cdarke Mar 08 '19 at 09:11
  • @cdrake, you are correct that it is important to know the purpose of brackets and single quotes and double quotes and when they are needed. Oftentimes I find myself writing a short script and say, "I am dealing with a number here. I don't need the brackets or quotes." But I do it anyway to maintain the habit. If I let it go in one instance, I will do it again the next time, and so on, then the habit is gone and I'll end up forgetting it when I really need it, leading to a buried error that could take much time and frustration to correct. Been there, don't need that. To each their own. – Randyman99 Mar 13 '19 at 18:51
16

Bash allow u to use =~ to test if the substring is contained. Ergo, the use of negate will allow to test the opposite.

fullstring="123asdf123"
substringA=asdf
substringB=gdsaf
# test for contains asdf, gdsaf and for NOT CONTAINS gdsaf 
[[ $fullstring =~ $substring ]] && echo "found substring $substring in $fullstring"
[[ $fullstring =~ $substringB ]] && echo "found substring $substringB in $fullstring" || echo "failed to find"
[[ ! $fullstring =~ $substringB ]] && echo "did not find substring $substringB in $fullstring"
Thiago Conrado
  • 726
  • 8
  • 15
  • 3
    I think `[[ ! $fullstring =~ $substringB ]]` is the most fitting answer to this question. thanks – Tms91 Sep 01 '22 at 09:00
7

As mainframer said, you can use grep, but i would use exit status for testing, try this:

#!/bin/bash
# Test if anotherstring is contained in teststring
teststring="put you string here"
anotherstring="string"

echo ${teststring} | grep --quiet "${anotherstring}"
# Exit status 0 means anotherstring was found
# Exit status 1 means anotherstring was not found

if [ $? = 1 ]
then
  echo "$anotherstring was not found"
fi
JJC
  • 9,547
  • 8
  • 48
  • 53
  • 23
    You are using a cannon to kill a mosquito – Jahid May 31 '15 at 14:09
  • 1
    Jahid is probably right, but, if someone is bent on this approach, this oneliner is more compact: ```if echo $teststring | grep -q $anotherstring ; then echo "found"; else echo "not found"; fi``` – JJC Sep 21 '17 at 14:02