Using a wildcard in a condition to match the beginning of a string

Trying to have a variable meet a string of text that varies by length. The part of the string that matters is the first couple of characters.

var1=hello  
if [ $var1 == hello ]; then  
    echo success  
fi

Or

var1=hello  
if [ $var1 == h*o ]; then  
    echo success  
fi

Outputs: success

But since I care care about the first 3 characters or so, this sounds logical, but is not working:

var1=hello  
if [ $var1 == hel* ]; then  
    echo success  
fi

Outputs: -bash: [: too many arguments

Since I only care about the first couple of characters, I can do:

var1=hello 
if [ ${var1:0:3} == hel ]; then 
    echo success  
fi

That would work, but I am looking for an explanation of why I am getting that error and a possible better written solution.


Solution 1:

When you use * in an if like that, it will do filename expansion. So in the first instance, h*o probably matched to a file in your current directory, and so the test passed.

The hel* matched to several files, and so became too many arguments for the if command.

Try using if [[ $var1 == hel* ]]; then

The double brackets turns the test into a regex, and the * wildcard will work as you expect.

Solution 2:

I have a trick I use to hack in regex without using builtin bash regex. Example is for #2. The way this works is grep returns no output (thus a nonexistant string) if it doesn't match anything. So there are two tests, -z means "null string" and -n is "has data."

if [ -n "`echo $var1 | grep -e 'h.*o'`" ] ; then
  echo 'water found'
fi