2

Consider the following script:

#! /bin/bash

line="confusing"

if [[ $line =~ [[:lower:]]* ]]
then
    echo "matches!"
else
    echo "does not match."
fi

While the above produce the expected result, the following does not:

#! /bin/bash

line="CoNfUsInG"

if [[ $line =~ [[:lower:]]* ]]
then
    echo "matches!"
else
    echo "does not match."
fi

This prints "matches!"
I am confused; isn't the regular expression [[:lower:]]* means zero or more lower case letters?

It gets even more confusing when the following also prints "matches!"

#! /bin/bash

line="CoNfUsInG"

if [[ $line =~ [[:digit:]]* ]]
then
    echo "matches!"
else
    echo "does not match."
fi

Anyone have an explanation to why this happens?

  • 1
    The key is "zero or more characters" -- there are zero lower/digit characters right at the beginning of that string. – glenn jackman Nov 13 '15 at 17:54
  • the regexp isn't anchored with ^ so there are zero-or-more matches anywhere in the string, not just at the beginning. Also, OP can use + instead of * if they want 1-or-more matches. – cas Nov 14 '15 at 0:05
10

The regular expression doesn't have to match the whole string. That's why you have ^ and $ for string beginning and end, respectively.

[[ CoNfUsInG =~ ^[[:lower:]]*$ ]] || echo no

CoNfUsInGlY, ^[[:lower:]]* (without the $) still matches, as there are zero lower-case letters at the beginning of the string.

  • ^[[:lower:]]*$ also matches the empty string. Use ^[[:lower:]]+$ if you want to match on at least one lowercase char in the string. – cas Nov 14 '15 at 0:07
  • @cas your RE ^[[:lower:]]+$ will match only if the string consists entirely of lowercase letters and it is not zero length. – roaima Nov 14 '15 at 0:19
  • yes, that's what i said. – cas Nov 14 '15 at 0:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.