Package: dash
Version: 0.5.7-4+b1
Severity: normal
joey@darkstar:~>cat testcase
#!/bin/sh
echo ${#@}
joey@darkstar:~>bash testcase a
1
joey@darkstar:~>posh testcase a
1
joey@darkstar:~>dash testcase a
1
good so far...
joey@darkstar:~>bash testcase a b
2
joey@darkstar:~>posh testcase a b
2
joey@darkstar:~>dash testcase a b
3
!!
joey@darkstar:~>bash testcase a b c
3
joey@darkstar:~>posh testcase a b c
3
joey@darkstar:~>dash testcase a b c
5
joey@darkstar:~>bash testcase aaa bbb cccc
3
joey@darkstar:~>posh testcase aaa bbb cccc
3
joey@darkstar:~>dash testcase aaa bbb cccc
12
posh:
${#name}
The number of positional parameters if name is *, @ or is
not specified, or the length of the string value of
parameter name.
bash:
${#name[subscript]} expands to the length of ${name[sub‐
script]}. If subscript is * or @, the expansion is the number
of elements in the array.
dash:
${#parameter} String Length. The length in characters
of the value of parameter.
So dash's documentation doesn't specify what it does for ${#@}. What its
actually doing is taking the length of the string consisting of all the
positional parameters, separated by spaces.
I have not checked if the behavior of ${#@} is standardized in any way.
If ${#@} is standardized, then dash should follow the standard.
Currently, a #!/bin/sh script cannot currently safely use ${#@}, because
/bin/sh can be dash or bash. If some package contains a #!/bin/dash
script, it could rely on the current behavior. OTOH, the behavior is
undocumented, and seems pretty useless, so it's unlikely someone would
go to the bother of using #!/bin/dash to get it. This might argue for
changing the behavior to match bash and posh even if there is not a
standard.
On the other hand, $# reliably yields the number of positional parameters
in all of bash, posh, and dash. So any script can use that. So, the easiest
fix would be to just document on its man page the special way bash handles
${#@} (and ${#*})
-- System Information:
Debian Release: 8.0
APT prefers unstable
APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.utf8, LC_CTYPE=en_US.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
Versions of packages dash depends on:
ii debianutils 4.4+b1
ii dpkg 1.17.22
ii libc6 2.19-13
dash recommends no packages.
dash suggests no packages.
-- debconf information excluded
--
see shy jo
Subject: Re: Bug#774001: ${#@} and ${#*} are incompatable with bash and posh
Date: Sun, 16 Aug 2015 15:33:40 +0200
On Fri, 26 Dec 2014 19:30:52 -0400 Joey Hess <[email protected]> wrote:
> Package: dash
> Version: 0.5.7-4+b1
> Severity: normal
> joey@darkstar:~>cat testcase
> #!/bin/sh
> echo ${#@}
> [snip]
> posh:
> ${#name}
> The number of positional parameters if name is *, @ or is
> not specified, or the length of the string value of
> parameter name.
> bash:
> ${#name[subscript]} expands to the length of
> ${name[subscript]}. If subscript is * or @, the expansion is the
> number of elements in the array.
Nitpick: this doesn't actually describe ${#@}. However, the actual
description of ${#parameter} further on explicitly documents what ${#@}
and ${#*} expand to, the same as $#.
> dash:
> ${#parameter} String Length. The length in characters
> of the value of parameter.
> So dash's documentation doesn't specify what it does for ${#@}. What its
> actually doing is taking the length of the string consisting of all the
> positional parameters, separated by spaces.
This is actually the length of the expansion of $@ or $* in a context
where word splitting is not performed, except if IFS is set to the empty
string.
> I have not checked if the behavior of ${#@} is standardized in any way.
> If ${#@} is standardized, then dash should follow the standard.
POSIX leaves the result of the expansion of ${#@} and ${#*} unspecified.
> Currently, a #!/bin/sh script cannot currently safely use ${#@}, because
> /bin/sh can be dash or bash. If some package contains a #!/bin/dash
> script, it could rely on the current behavior. OTOH, the behavior is
> undocumented, and seems pretty useless, so it's unlikely someone would
> go to the bother of using #!/bin/dash to get it. This might argue for
> changing the behavior to match bash and posh even if there is not a
> standard.
Dash's ${#*} may be a faster alternative to temp="$*"; ${#temp}.
However, the silently inconsistent behaviour across shells is a good
reason not to use it.
> On the other hand, $# reliably yields the number of positional parameters
> in all of bash, posh, and dash. So any script can use that. So, the easiest
> fix would be to just document on its man page the special way bash handles
> ${#@} (and ${#*})
Indeed, there is no reason to use ${#@} and ${#*} in bash/posh.
--
Jilles Tjoelker
Debbugs is free software and licensed under the terms of the GNU General
Public License version 2. The current version can be obtained
from https://bugs.debian.org/debbugs-source/.