32

I'm using Ubuntu system shell, not bash, and I found the regular way can not work:

#!/bin/sh
string='My string';

if [[ $string =~ .*My.* ]]
then
   echo "It's there!"
fi

error [[: not found!

What can I do to solve this problem?

Victor Sergienko
  • 13,115
  • 3
  • 57
  • 91
harryz
  • 4,980
  • 6
  • 31
  • 34

3 Answers3

31

The [[ ... ]] are a bash-ism. You can make your test shell-agnostic by just using grep with a normal if:

if echo "$string" | grep -q "My"; then
    echo "It's there!"
fi
Christopher Neylan
  • 8,018
  • 3
  • 38
  • 51
  • Thanks! That's what I need, and I also realized what is the bashism:http://mywiki.wooledge.org/Bashism – harryz Jan 14 '14 at 14:11
29

Using grep for such a simple pattern can be considered wasteful. Avoid that unnecessary fork, by using the Sh built-in Glob-matching engine (NOTE: This does not support regex):

case "$value" in
  *XXX*)  echo OK ;;
  *) echo fail ;;
esac

It is POSIX compliant. Bash have simplified syntax for this:

if [[ "$value" == *XXX* ]]; then :; fi

and even regex:

[[ abcd =~ b.*d ]] && echo ok
hoijui
  • 3,615
  • 2
  • 33
  • 41
gavenkoa
  • 45,285
  • 19
  • 251
  • 303
12

You could use expr:

if expr "$string" : "My" 1>/dev/null; then
  echo "It's there";
fi

This would work with both sh and bash.

As a handy function:

exprq() {
  local value

  test "$2" = ":" && value="$3" || value="$2"
  expr "$1" : "$value" 1>/dev/null
}

# Or `exprq "somebody" "body"` if you'd rather ditch the ':'
if exprq "somebody" : "body"; then 
  echo "once told me"
fi

Quoting from man expr:

   STRING : REGEXP
          anchored pattern match of REGEXP in STRING
Nick Bull
  • 9,518
  • 6
  • 36
  • 58
devnull
  • 118,548
  • 33
  • 236
  • 227
  • This is the traditional, portable solution if you really require regular exoressiins. However, a lot of the time, `case` is sufficient; and `grep` gets the job done as well, and is probably more familiar to most users. – tripleee May 22 '15 at 04:07
  • expr is build in to Bourne shell and much faster, we should favor this over other methods. – Kemin Zhou Oct 17 '16 at 21:27
  • 1
    All well and good if you **always want to match at the beginning of the string**, otherwise it won't work (why the heck did they put that restriction in?) - and BTW this answer does not satisfy the OP's specific case, matching **anywhere in the string**. – user9645 Jan 20 '20 at 16:56
  • @user9645 Calm down. expr takes a regular expression, which is exactly what the OP asked for. You can search practically anything. – Johan Boulé Jan 06 '22 at 14:02
  • But, @user9645 is correct. The regex in the question includes a leading and trailing `.*`, which you have removed in your answer, implying they weren't necessary, but without the leading `.*`, it fails. – gilly3 Jul 28 '22 at 23:13