Solved expr(1) do not honor \+ regex

Hello,

On Freebsd 14.1-Release, I tried expr "Hello 7.1" : '.* \([.0-9]\+\)'
which returns empty string, while \+ replaced by * returns 7.1.

The man page says expressions should be basic regular expression, and I found that \+ is. Is it a bug? A mistakes I did? Thanks for your help.
 
[…] and I found that \+ is. […]
Where’d you find that? It is Basic Regular Expressions (capitalized as if it was a proper name), not basic regular expressions. re_format(7) explains:​
Obsolete (“basic”) regular expressions differ in several respects. | is an ordinary character and there is no equivalent for its functionality. + and ? are ordinary characters, and their functionality can be expressed using bounds ({1,} or {0,1} respectively).​
 
expr(1) does not evaluate regexps. It evaluates arithmetic expressions. Why would you think it should honor regexps?
 
expr(1) does not evaluate regexps. It evaluates arithmetic expressions. Why would you think it should honor regexps?
Yes it does. Because it is described in the manual:

Code:
expr1 : expr2
             The ":" operator matches expr1 against expr2, which must be a
             basic regular expression.  The regular expression is anchored to
             the beginning of the string with an implicit "^".

             If the match succeeds and the pattern contains at least one
             regular expression subexpression "\(...\)", the string
             corresponding to "\1" is returned; otherwise the matching
             operator returns the number of characters matched.  If the match
             fails and the pattern contains a regular expression subexpression
             the null string is returned; otherwise 0.
 
Yes it does. Because it is described in the manual:

Code:
expr1 : expr2
             The ":" operator matches expr1 against expr2, which must be a
             basic regular expression.  The regular expression is anchored to
             the beginning of the string with an implicit "^".

             If the match succeeds and the pattern contains at least one
             regular expression subexpression "\(...\)", the string
             corresponding to "\1" is returned; otherwise the matching
             operator returns the number of characters matched.  If the match
             fails and the pattern contains a regular expression subexpression
             the null string is returned; otherwise 0.
This works:

Code:
slippy$ expr "Hello 7.1" : '..* \([.0-9][.0-9]*\)'  
7.1
slippy$

It doesn't support PCRE.

What you want is gexpr from sysutils/coreutils, which does support PCRE.

Code:
slippy$ gexpr "Hello 7.1" : '..* \([.0-9][.0-9]*\+\)'
7.1
slippy$
 
Thanks, I can mark the post as solved. I simply replace \+ by {1,} as documented. My goal is to patch a port with minimal modification thus gexpr is not an option. Indeed linux expr seems to use extended form.
 
Back
Top