42

I was reading about positional parameters in Unix and then I found this info:

The shell allows a command line to contain at least 128 arguments; however, a shell program is restricted to referencing only nine positional parameters, $1 through $9, at a given time. You can work around this restriction by using the shift command.

So I created a simple shell script called file like the following:

#! /bin/bash
echo $14

then ran it like the following :

./file 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

and I got 14!

So how is that possible if the shell doesn't allow more than 10 parameters (from $0 to $9) without using shift command?

9

1 Answer 1

69

When you run

echo $14

what happens is that bash interprets the argument $14 as $1 and 4 separately. It then expands $1 (which in this case is equal to "1"), then appends the string 4 to it, which results in "14". Although that was the result you were expecting, it's actually a side effect from Bash's actual behaviour. Like @steeldriver mentioned in comments, running your script like this instead :

./file a b c d e f g h i j k l m n

and then calling echo $14 won't output "n" but "a4".

Note that wrapping the variable in double-quotes :

echo "$14"

will still not expand the variable correctly in Bash. The standard method is to use curly braces around the variable name :

echo ${14}

For more information, see the official documentation for parameter expansion in Bash. It can do a lot more cool things too, like

${14^^*}

to capitalize argument no.14. Give it a read! :)

7
  • 9
    Note that that "bug" (unfortunately mandated by POSIX) where $14 is ${1}4 instead of ${14} was fixed in csh, ash, tcsh, rc, es, akanga and zsh (when not in sh/ksh emulation), though broken again in some ash derivatives for POSIX compliance. Jan 25, 2021 at 9:35
  • 2
    Just wrapping the variabled in double quotes does not work: bash -c 'echo "$14"' - WTF => WTF4.
    – user313992
    Jan 25, 2021 at 9:59
  • 3
    If that worked for you, it's because you had used dash (Debian's /bin/sh) where simply echo $14 would've worked too: dash -c 'echo $14' - a b c d e f g h i j k l m n => n.
    – user313992
    Jan 25, 2021 at 10:01
  • 4
    @ilkkachu, fixed or broken depending on how you want to look at it. As per my first comment here, it used to be fine but was broken (IMO) in newer versions for POSIX compliance. Jan 25, 2021 at 14:32
  • 2
    @StéphaneChazelas, well. As far as I understand, Dash is meant to implement the POSIX shell language as it is, instead of creating a new but actually sane language. So in that context, behaviour that's both noncompliant and different from almost all other POSIX-like shells seems unquestionably a bug.
    – ilkkachu
    Jan 25, 2021 at 22:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .