0

I want to detect if the input argument contains some sub-string.

I tried below scripts:

#1:

#!/bin/sh

if  [ $1 = *abc* ]
then
    echo contains abc
else
    echo not contains abc
fi

#2:

if  [ "$1" = "*abc*" ]
then
    echo contains abc
else
    echo not contains abc
fi

#3:

if  [ "$1" = *"abc"* ]
then
    echo contains abc
else
    echo not contains abc
fi

All #1 ~ #3 don't work.

But below ones with [[ can easily work:

#4:

if  [[ $1 = *"abc"* ]]
then
    echo contains abc
else
    echo not contains abc
fi

#5:

if  [[ $1 = *abc* ]]
then
    echo contains abc
else
    echo not contains abc
fi

So is it possible to make the single [ work?

ADD 1 - 10:55 AM 9/21/2021

Just found a VERY USEFUL thread:

What is the difference between the Bash operators [[ vs [ vs ( vs ((?

smwikipedia
  • 1,173
  • 10
  • 17
  • So, you tagged this with [[tag:bash]], and ask if it's possible to make the single `[` work with the pattern. Counter-question: is there a reason to want to use `[` in particular, when Bash supports `[[` which does exactly what you want? – ilkkachu Sep 21 '21 at 07:35

2 Answers2

0

[[ is a shell builtin. It is a more versatile version of [, which is an executable in /usr/bin (see the documentation and man page of test for further details).

[ is more portable, while [[ is more versatile, and it's generally the variant you should use.

if  [[ $1 == *"abc"* ]]; then
    echo "substring present"
else
    echo "substring not present"
fi

Another good way of testing for substring is to use the regex operator:

if [[ "$1" =~ .*"abc".* ]]; then
    echo "contains"
else
    echo "doesn't contain"
fi

Note that the expression after =~ is a regular expression and not just globbing.


Yet another way of checking substrings is to use case:

case $1 in
    *"abs"*)
        echo "substring present"
        ;;
    *)
        echo "substring not present"
        ;;
esac

Alternatively, you can use grep, as CPH explained in his post. However you need to make sure to use a here-doc:

if grep -q "abc" <<< "$STR"; then
    echo "substring present"
else
    echo "substring not present"
fi
polemon
  • 11,133
  • 11
  • 69
  • 111
  • 1
    I remember `[[` is a keyword, which is syntax concept, while a `builtin` is some built-in command. Correct me if I am wrong because I am new to bash. – smwikipedia Sep 21 '21 at 02:20
  • @smwikipedia it is a command, invoking `test` just like `[`, except it's part of bash. Run `man test` to get a man page for the "normal" `[`. – polemon Sep 21 '21 at 02:22
  • I just tried `type [[`. It gives me `[[ is a shell keyword`. And I tried `type [`. It gives me `[ is a shell builtin`. I tried in CygWin. – smwikipedia Sep 21 '21 at 02:24
  • @smwikipedia you can also do `help [[` to get a quick synopsis from within bash. – polemon Sep 21 '21 at 02:25
  • 1
    @smwikipedia that's because the modern bash abstracts a bunch of "standard" POSIX commands like `true`, `false`, and a bunch others, like `[`. Technically there's little difference, as it doesn't work like an operator. Operators for instance are things like '&' to run something in the background, or `<` and `>` and `|` to re-route STDOUT and STDIN (and STDERR). – polemon Sep 21 '21 at 02:30
-2

Is there a reason you want to use single brackets?

A simpler way would be something like this:

if echo "$1" | grep 'abc' > /dev/null; then
    # Do if true substring found
else
    # substring not found
fi

If you're not familiar with the grep command, it just searches a string for the parameter/value you give. You can ignore case if you want using the -i flag, the above will look specifically for a lowercase 'abc' in your parameter '$1'

Philippos
  • 13,237
  • 2
  • 37
  • 76
CPH
  • 105
  • 2
  • Just curious. It seems `[[` is an enhancement comes after `[`. Just wonder how people do that before `[[`. – smwikipedia Sep 21 '21 at 02:18
  • 1
    Ahh I see. I'll give my understanding here: `[[ ]]` are used for operators (greater than, less than, etc). `[ ]` is used for string comparisons. I just noticed this though, what you have in your question may work (not 100% sure though). You just need to change `=` to `==` (I believe) – CPH Sep 21 '21 at 02:42
  • The only hesitation I have on it working is the wildcard `*`. I don't know if that will be accepted as proper syntax – CPH Sep 21 '21 at 02:44
  • I tried `if [ "$1" == *abc* ]`, still doesn' work. I will try some more. – smwikipedia Sep 21 '21 at 02:45
  • the only thing that MAY work would be `*"abc"*`, but even then I doubt it. doing `*abc*` will not compile, and will probably give an error similar to "*abc* is not a command" or something along those lines. – CPH Sep 21 '21 at 02:47