Hello,

On 10/26/2016 12:15 PM, Paul Eggert wrote:
There's no bug here: "expr E" exits with status 1 if E evaluates to 0, and expressions 
like "0 : '\([0-9]\)$'" do evaluate to 0.

Worth mentioning that this is a known "gotcha", explained here:
  http://www.pixelbeat.org/docs/coreutils-gotchas.html#expr

And to elaborate as to why, consider the same regex without grouping - 'expr' 
will return the *number of characters matched*,
so:

    $ expr 0 : '[0-9]$'
    1
    $ expr 1 : '[0-9]$'
    1
    $ expr 4 : '[0-9]$'
    4
    $ expr 9 : '[0-9]$'
    1
    $ expr a : '[0-9]$'
    0

Because you've added grouping, 'expr' returns the *actual matched characters*:

    $ expr 0 : '\([0-9]\)$'
    0
    $ expr 1 : '\([0-9]\)$'
    1
    $ expr 4 : '\([0-9]\)$'
    4
    $ expr 9 : '\([0-9]\)$'
    9
    $ expr a : '\([0-9]\)$'
    [[ empty string ]]


And the "gotcha" is that 'expr' uses the resulting value as exit code. If the value is 
the string "0" or the value 0 or an empty string - the exit code will be 1 (failure). In 
your example, the exit code should not be used to distinguish between matched '0' and non-matching 
string:

    $ expr 0 : '\([0-9]\)$' ; echo $?
    0
    1
    $ expr a : '\([0-9]\)$' ; echo $?
1

Instead, if you use grouping, save the result into a variable and check if it's 
empty:

    $ A=$(expr 0 : '\([0-9]\)$')
    $ test -n "$A" && echo "matched" || echo "did not match"
    matched



regards,
 - assaf













Reply via email to