bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: mysteries with the placeholder variable _


From: Lawrence Velázquez
Subject: Re: mysteries with the placeholder variable _
Date: Sat, 12 Dec 2020 19:27:57 -0500

> On Dec 12, 2020, at 5:51 PM, Léa Gris <lea.gris@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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]