bashmacosshellexpr

Why do I get a syntax error when using expr in bash(MacOS)?


I'm just starting to learn shell, and I felt really puzzled when I got a syntax error in this simple code :

str="Hello world!"
echo $(expr length "$str")

But this code can work on Ubantu actually. Is it because my bash version is outdated? Or is it a problem with the MacOS system?

I have updated my bash version, now it is GNU bash 5.1.16, but this problem still exists. I'm really confused right now.


Solution

  • expr on MacOS does not accept the argument length. The man page contains this rather oblique passage:

    According to the POSIX standard, the use of string arguments length, substr, index, or match produces undefined results. In this version of expr, these arguments are treated just as their respective string values.

    In other words, expr length simply returns length and expr length "$str" is a syntax error because expr only accepts a single argument.

    This isn't a problem really, because Bash scripts should basically never need to use expr at all. Bash has built-in facilities which replace more or less all of the legacy expr logic.

    To get the length of a string in Bash, try

    ${#str}
    

    For more, probably start with the parameter expansions in Bash.

    expr is an OS utility which is independent of your shell, so it doesn't really make any difference which version of Bash you are using, or in fact whether you are using a shell at all.

    If you find yourself in a situation where you need to get a string's length portably in a POSIX sh / Bourne shell script, perhaps resort to Awk.

    len=$(printf '%s\n' "$str" | awk '{ print(length($0)) }')
    

    (This will print multiple numbers if str contains multiple lines. It's not hard to change it if you need to find the total length of a string with embedded newlines, but I'm guessing we don't need to go there.)