By chronological order, in various shells:
- csh (late 70s):
$argv[$n]
(also works in zsh since 1991 and fish since 2005)
- zsh (1991):
$argv[n]
/ $@[n]
/ $*[n]
(the last too also supported by yash but only with extra braces: ${@[n]}
/ ${*[n]}
)
- rc (early 90s):
$$n
/ $*($n)
(also works in es, akanga)
- ksh93 (1993):
${@:n:1}
, ${*:n:1}
(also supported by bash since 1996; zsh also since 2010, though you need ${@:$n:1}
or ${@: n:1}
there to avoid conflict with csh-style modifiers and see there about the "$*"
case)
- bash (1996):
${!n}
- zsh (1999):
${(P)n}
.
Remember that in ksh93/bash/yash, you need to quote parameter expansions in list contexts at least, and csh can hardly be used to write reliable code.
In bash
, there's a difference between "${!n}"
and "${@:n:1}"
in list context when the nth positional parameter is not set in that the latter then expands to no argument at all whilst the former expands to one empty element.
In Bourne-like shells (but not the Bourne shell where that won't work for indices past the 9th), and with standard POSIX sh syntax, you can also do:
eval "nth=\${$n}"
There will also be differences in behaviour among all those if $n
does not contain the canonical decimal representation of an integer number strictly greater than 0. If you can't guarantee that will be the case, using most of those (not just the eval
one) would introduce an arbitrary command execution vulnerability (the only exceptions being with rc
and maybe csh
above).
Also remember that except in zsh
(with echo -E - $argv[n]
), yash
(with ECHO_STYLE=raw echo "${*[$n]}"
) and fish
(with echo -- $argv[$n]
), echo
can't be used to output arbitrary data, use printf '%s\n' ...
instead).
$()
, with parameter expansion,${}
. So you're starting from the wrong section in the manual... – Toby Speight Mar 10 '22 at 14:11