Martijn Dekker <
mar...@inlv.demon.nl>:
> Op 27-04-18 om 09:07 schreef Helmut Waitzmann:
>> while ${1+:} false
>
> I hadn't seen that trick before. Clever, but non-obvious. To
> understand what it does, anyone reading the code requires a keen
> understanding of how the shell's parameter substitution and empty
> removal mechanisms work -- including that the command name is just
> another argument and therefore subject to empty removal, so that the
> next argument becomes the command name instead.
You are totally right. I should have added a comment.
>
> The following works the same but is rather easier to understand:
>
> while [ "$#" -gt 0 ]
Yes, of course. Because
>> while ${1+:} false
was a change from my incorrect (see some posts before)
“while ${arg+:} false”,
I didn't bother to replace it by
“while [ "$#" -gt 0 ]”,
which is an invocation of the (maybe non‐built‐in) “[” utility.
Let me explain my motivation for
“${arg+:} false”:
As Stephane Chazelas wrote, an equivalent command for
“${arg+:} false”
using the “[” utility would be
“[ "${arg+set}" = set ]”.
Another one would be
“[ -n "${arg+set}" ]”.
A third one would be
“[ ${arg+set} ]”.
All of these alternatives use the “${arg+...}” mechanism of the
shell; and it turns out, that the core logic of these alternatives
(i.e. to investigate whether the parameter “arg” is set or unset)
is achieved by the “${arg+...}” mechanism rather than by the “[”
utility. At this point, before invoking “[”, the shell already
knows, whether the parameter “arg” is set or unset, so it seems to
be rather pointless to me to transform that knowledge into the
string “set” resp. “” or—in the third case—no string, forget that
knowledge and finally let the “[” utility examine its parameter to
regain it.
Now, if “[” is a non‐built‐in utility, it might be quite costly to
invoke it (using one of the “exec” family of functions).
Therefore, I asked myself, is there a way to make that knowledge
known to the shell script without invoking a non‐built‐in utility?
As you already wrote, there is one:
Invoke the shell built‐in “:” or the probably built‐in “false”,
using the fact, that parameter expansion and empty unquoted word
removal are done before the name of the utility to be invoked is
determined:
“${arg+:} false”
will invoke either “: false” or “false”, depending on whether the
shell variable “arg” is set or unset.
If “false” actually is a non‐built‐in utility, the shell function
“false() { return 1; }”
could be defined to replace it w.r.t. invoking a simple command,
which will avoid calling one of the “exec” family of functions.