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/'
and:
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.
\(and\)were used instead of(and)as above link said? – cuonglm Feb 15 '16 at 03:53