I am reading the source code of the Maven wrapper written for the Bourne shell. I came across these lines:
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then
# snip
expr when used with arg1 and arg2 and a : matches arg1 against the regex arg2. Normally, the result would be the amount of matching characters, e.g.:
$ expr foobar : foo
3
However, when using capturing parentheses (\( and \)), it returns the content of the first capturing parentheses:
$ expr foobar : '\(foo\)'
foo
So far, so good.
If I evaluate the expression from the source quoted above on my machine, I get:
$ javaExecutable=$(which javac)
$ expr "$javaExecutable" : '\([^ ]*\)'
/usr/bin/javac
For a non-existing executable:
$ nonExistingExecutable=$(which sjdkfjkdsjfs)
$ expr "$nonExistingExecutable" : '\([^ ]*\)'
Which means that for a non-existing executable the output is a empty string with newline.
What's puzzling me in the source is how the output of which javac (arg1 to expr) ever returns the string no?
Is there some version of which which, instead of returning nothing, returns no when no executable can be found?
If not, this statement always evaluates to true and that would be weird.
whichoutputs "no 'foo' found" or something like that. The pattern[^ ]*matches a string of non-spaces, and usually a regex match picks the first hit, hitting thenoat the start. I don't know what implementation would do that, though. zsh gives me "foo not found", and csh gives "foo: Command not found.".whichdoes this? Don't have a machine to try it on, currently.whichis the right tool here at all, but any reasonably competent programmer would have checked the return value ofwhichinstead of trying to parse anosubstring from the output of a failedwhichinvocation. You already know where this code is – please write a patch and submit it upstream :)whichis not the way to do it,command -vis (it’s available pretty much everywhere and it produces much more easily parseable output). And the rest of the script is even worse (I count at least a dozen issues not including the inconsistent coding style just in the bits leading up to the start of the first function definition).