I need a explanation of why:

$test=`expr "hello" : "\([a-z]*\)"`; echo $test

would print out hello, where as:

$test=`expr "hello" : "hel"`; echo $test

would return the number of characters matching.

And also:

$ test=`expr "hello123there" : ".*o\([0-9]*\)"t`; echo $test

notice after .* I have to specify the o for it to return 123, otherwise it would not return anything.

2 Answers 2


It's right there in the man page, E.G. http://ss64.com/bash/expr.html

Pattern matches return the string matched between ( and ) or null; if ( and ) are not used, they return the number of characters matched or 0.

  • @Yangfan: You mean why \( and \) were used instead of ( and ) as above link said?
    – cuonglm
    Feb 15, 2016 at 3:53
  • @cuonglm I was looking for an answer as to why substring pattern is only matched if characters before and after the pattern are specified? if this confuses you I can update my question with an example Feb 15, 2016 at 3:55
  • @Yangfan: I updated my answer with more details. Please remove chatty comments. Thanks.
    – cuonglm
    Feb 15, 2016 at 4:34

That's how expr matching expression works.

If the pattern contains at least one regular expression subexpression [\(...\)], the string matched by the back-reference expression \1 shall be returned. hello matched \([a-z]*\), so you got it back.

expr used BRE, so you have to escape \( and \) to denote a subexpression. Using ( and ) is considered literal in BRE.

Otherwise, you got the number of characters matched.

In expr "hello123there" : ".*\([0-9]*\)"t, you got empty string returned. That's because the greediness of regular expression, the longest substring will be matched.

Because * match zero or more characters, so [0-9]* can match zero times, and .* will match the longest substring hello123. That's why you got the empty string.

If you have perl, you can try:

printf "hello123there" | perl -Mre=debugcolor -ne 'print $1 if /.*([0-9]*)t/'


printf "hello123there" | perl -Mre=debugcolor -ne 'print $1 if /.*o([0-9]*)t/'

to see the difference.

Note that you should always double quotes your variables. Leaving variables un-quote can make your script choked and leading to security holes.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .