# Why does the positional parameter syntax `\${18}` need braces?

I'm currently learning the command line and I'm learning Positional Parameters. And I saw that the Positional Parameters end at nine, To use more than \$9, I must put them in curly braces, like: \${18}. But what is the story of the nine Positional Parameters and not allowed to put more of them in shape:\$18?

• \$18 is understood as \${1}8. I guess the lexer is simpler like this. Dec 12, 2021 at 19:40
• technically, your opening statement is misleading, you say there's only nine positional parameters, yet you show that there is no limit of 9 Dec 12, 2021 at 21:31
• I would be very surprised if the story was anything other than that it was done like that in the first implementation and it stuck due to backward compatibility. Dec 12, 2021 at 21:58
• I find it's helpful if you view `\${var}` as the "official" way to expand shell variables, and think of dropping the curly braces as a shortcut which is enabled in some, but not all, cases.
– R.M.
Dec 14, 2021 at 13:22

## 1 Answer

The list of positional parameters can be as long as required and as current resource limits allows. This means that there may be well over 9 elements in the list. As you have already noticed, elements 10 and later may be accessed by adding braces around the number, as in `\${12}`.

The reason the braces are needed to access elements beyond element 9 in most POSIX-like shells is because the POSIX standard says so.

A positional parameter is a parameter denoted by the decimal value represented by one or more digits, other than the single digit 0. The digits denoting the positional parameters shall always be interpreted as a decimal value, even if there is a leading zero. When a positional parameter with more than one digit is specified, the application shall enclose the digits in braces.

(From here, "Shell Command Language: Positional Parameters")

The word "application" in the text above means "your script".

The simplest form for parameter expansion is:

`\${parameter}`

The value, if any, of `parameter` shall be substituted.

The parameter name or symbol can be enclosed in braces, which are optional except for positional parameters with more than one digit or when parameter is a name and is followed by a character that could be interpreted as part of the name.

(From here, "Shell Command Language: Parameter Expansion")

Note also that addressing any other than the first few positional parameters directly is quite a rare thing to do. It's common to access `\$1` and `\$2`, but `\$3` and the others see very little use. It's more common to iterate over the list, as in

``````for argument do
# use "\$argument" here
done
``````

... or to use the whole list at once with `"\$@"`.

Also note that some shells may choose to ignore the standard. Here's the `zsh` shell, which does not try to be strictly POSIX compliant:

``````\$ set -- a b c d e f g h i j k l m n o p
\$ print \$13
m
\$ print \$16
p
``````

... unless it's emulating `sh`:

``````\$ emulate sh
\$ print \$13
a3
``````

The `a3` string comes from outputting `\$1` followed by `3`.

• In the Bourne shell, `\${10}` won't work and `\$10` is `\${1}0` likely like that for compatibility with the Thompson shell. POSIX most likely specifies it like that because it's how it's done in ksh (which does it like that for Bourne compatibility, though allows `\${10}` as an extension). Dec 13, 2021 at 17:20
• Not every reader here may be aware that Bourne, referenced in the above comment, is much older than currently-common `/bin/sh` implementations -- such as `ash` and `dash` -- which are compliant with the early-1990s POSIX.2 standard, which Bourne predates by decades. Dec 14, 2021 at 17:30