local var="$@" doesn't behave like every other system

Bug #1943964 reported by raf
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
dash (Ubuntu)
New
Undecided
Unassigned

Bug Description

With Ubuntu (for many years), the following code in /bin/sh (i.e. dash):

  f()
  {
    local v="$@"
    echo "<$v>"
  }
  f "$@"

behaves differently to /bin/sh on Debian, macOS, FreeBSD, Solaris (/usr/xpg4/bin/sh).
The behaviour of "$@" is very special. When there are no arguments, it completely
disappears (i.e. even the surrounding quotes disappear so that there are no words). When
there are arguments, it replicates those arguments perfectly (i.e. it effectively produces
multiple quoted arguments if necessary).

The described behaviour applies when "$@" is used for local variable assignment on Ubuntu,
which sounds consistent with other uses of "$@" and therefore correct, but it doesn't
match the behaviour on any other system, and is therefore a problem for shell portability.
On the other systems mentioned above, the behaviour of "$@" when used as the value of a
variable assignment (local or not) is as though "$*" had been used (i.e. it produces a
single argument containing all the words).

The difference is clear when the arguments contain multiple words. On Ubuntu, only
the first word is assigned to v. Any subsequent words are treated as subsequent variable
names. This goes unnoticed if the subsequent words are valid variable identifiers.
But if the subsequent words are not valid identifiers, then dash emits a "bad variable name"
error message.

Note that without the "local" keyword, "$@" does behave like "$*" (like all the other systems).

You might think that this is correct behaviour, but it is contrary to non-local variable
assignment, and contrary to all other systems, and is therefore unhelpful. Please change
it to behave like dash on other systems, e.g. debian.

This behaviour has been witnessed on ubuntu-16.x and ubuntu-20.04.

Revision history for this message
raf (9-ubu8tu-9) wrote :

I thought I'd illustrate the problem. Given a #!/bin/sh script like this called tst:

    #!/bin/sh
    f()
    {
        local v="$@"
        echo "<$V>"
    }
    f "$@"

On Debian, Fedora, FreeBSD, OpenBSD, macOS, and Solaris, the arguably incorrect
but more useful behaviour is:

    > ./tst a b c
    <a b c>
    > ./tst 1 2 3
    <1 2 3>

On Ubuntu, the arguably correct but less useful behaviour is:

    > ./tst a b c
    <a>
    > ./tst 1 2 3
    ./tst: 4: local: 2: bad variable name

On NetBSD, the behaviour is very similar to Ubuntu's, but not identical:

    > ./tst a b c
    <a>
    > ./tst 1 2 3
    local: 2: bad variable name
    <1>

It seems that "bad variable name" is a fatal error on Ubuntu, but not on NetBSD.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.