> On Dec 12, 2020, at 5:51 PM, Léa Gris <lea.g...@noiraude.net> wrote: > > It raises multiple observations: > > - I thought the placeholder variable _ was a sinkhole like /dev/null.
It is not. I expect you've been deceived by countless examples like: read var1 var2 _ var3 _ var4 Your three non-dash shells explicitly consider $_ to be a special variable and overwrite it regularly. This may contribute to the misconception that assigning to it has no effect. The bash 5.0.17 man page: _ At shell startup, set to the absolute pathname used to invoke the shell or shell script being executed as passed in the environment or argument list. Subsequently, expands to the last argument to the previous simple command executed in the foreground, after expansion. Also set to the full pathname used to invoke each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file currently being checked. The ksh93u+ man page: _ Initially, the value of _ is an absolute pathname of the shell or script being executed as passed in the environment. Subsequently it is assigned the last argument of the previous command. This parameter is not set for commands which are asynchronous. This parameter is also used to hold the name of the matching MAIL file when checking for mail. While defining a compound variable or a type, _ is initialized as a reference to the compound variable or type. When a discipline function is invoked, _ is initialized as a reference to the variable associated with the call to this function. Finally when _ is used as the name of the first variable of a type definition, the new type is derived from the type of the first variable (See Type Variables below.). The zshparam(1) man page for zsh 5.8: _ <S> The last argument of the previous command. Also, this parameter is set in the environment of every command executed to the full pathname of the command. As you noticed with ksh, one can't be sure that these shells will gracefully handle a user writing to $_, which is why Greg's FAQ discourages doing so (https://mywiki.wooledge.org/BashFAQ/001): Note that this usage of _ is only guaranteed to work in Bash. Many other shells use _ for other purposes that will at best cause this to not have the desired effect, and can break the script entirely. It is better to choose a unique variable that isn't used elsewhere in the script, even though _ is a common Bash convention. > It seems like it can get assigned values within arithmetic expressions > in bash, dash and zsh Be careful how you test this hypothesis. The command : $((_=666)) might expand to : 666 so one might expect the non-dash shells to overwrite $_ with "666" anyway, since that is the last argument of the command. Indeed: % cat /tmp/underscore_test unset _ : $((_=666)) 'last arg' printf '<%s>\n' "$_" % bash /tmp/underscore_test <last arg> % ksh /tmp/underscore_test <last arg> % zsh /tmp/underscore_test <last arg> One might try ((_=666)), which doesn't expand to "666". Here the behaviors diverge significantly immediately after the attempted assignment, but all three shells recover after the subsequent command: % cat /tmp/underscore_test unset _ ((_=666)) printf '<%s>\n' "$_" : hi printf '<%s>\n' "$_" % bash /tmp/underscore_test <666> <hi> % ksh /tmp/underscore_test <-3.02546243348e-123> <hi> % zsh /tmp/underscore_test <_> <hi> These might not be perfect experiments (I'm in a bit of a rush), but the point stands: Writing to $_ is inconsistent and unpredictable and you shouldn't do it. > - The weird working of ksh if out of scope here, look like any > number not power of 2 produces the strange output that is not even > an integer. Given ksh's age and expectation that users are not writing to $_, I wouldn't be surprised if doing so triggers some sort of bug. vq