@kkachu explicou melhor do que eu poderia. Vou apenas adicionar uma nota de histórico.
O shell que veio com as primeiras versões do Unix (mais tarde chamado de shell Thompson) não tinha nenhuma variável, mas você já podia escrever scripts simples que usassem parâmetros.
sh [ name [ arg1 ... [ arg9 ] ] ] The name is the name of a file which will be read and in‐ terpreted. If not given, this subinstance of the shell will continue to read the standard input file. In command lines in the file (not in command input), character sequences of the form "$n", where n is a digit 0, ..., 9, are replaced by the nth argument to the invo‐ cation of the shell (argn). "$0" is replaced by name.
$1
... $n
já eram os argumentos e $0
o nome do script (não o
1º argumento), mas não foram chamados parâmetros posicionais .
Observe que, naquela época, $1
foi literalmente substituído pelo primeiro argumento antes da interpretação do shell.
Por exemplo, um script que tinha:
echo $1
chamado como
sh script 'foo; echo bar'
executaria echo foo; echo bar
. Esse shell era muito simples, escrito para computadores com poucas centenas de kilobytes de memória.
A shell Bourne chegou quase uma década depois (no final dos anos 70) com uma versão do Unix que introduziu o ambiente e outras coisas boas.
O shell Bourne veio com variáveis e muito mais construções de programação.
A terminologia parâmetro posicional , pelo menos quando se trata de shells Unix, foi introduzida pelo shell Bourne, e referenciada à mesma coisa, $1
... $n
para os argumentos do script (e $0
ainda é o nome do script). Como no shell Thompson, você poderia se referir apenas aos primeiros 9 argumentos ( $1
to $9
) com parâmetros posicionais (mas use shift ou "$@"
ou for i do
loops para acessar o restante) (e isso também explica (portabilidade para trás) porque você precisa de ${10}
em vez de $10
nas implementações mais modernas de sh
para as 10 primeiras).
Desta vez, sh script 'foo; echo bar'
não causou mais que echo bar
seja executado, mas mesmo assim o Bourne shell introduziu o infame split + glob, eu suponho não quebrar muito compatível com o shell Thompson, então script 'foo *'
script
tem echo $1
ainda chamou echo
com foo
e a lista de arquivos no diretório atual como argumentos (como no shell Thompson, mas desta vez através de um mecanismo diferente).
scripts também foram chamados de procedimentos de shell (note que o shell Bourne ainda não tem funções):
2.0 Shell procedures The shell may be used to read and execute commands contained in a file. For example, sh file [ args ] calls the shell to read commands from file. Such a file is called a command procedure or shell procedure. Arguments may be supplied with the call and are referred to in file using the positional parameters $1, $2...
As funções foram introduzidas pela primeira vez no shell Korn (baseado no shell Bourne) no início dos anos 80 com um
function foo {
...
}
sintaxe.
Funções foram eventualmente adicionadas ao shell Bourne, mais tarde, em SysVR2 (1984), com uma sintaxe diferente:
foo() any-command
(mas com comportamento inesperado quando any-command
era um comando simples e tinha redirecionamentos que provavelmente é a razão pela qual o POSIX requer apenas comandos compostos (como { ...; }
o mais usado) ser reconhecido lá para o POSIX sh
).
No shell Korn e Bourne, $0
na função ainda era o nome do script, não o nome da função (enquanto os parâmetros $1
, $2
posicional se referem aos argumentos da função).
Isso mudou em ksh93
para o estilo function f {
da definição da função, onde $0
se torna o nome da função na função.
Em zsh
, $0
é o nome da função, como em ksh93. zsh
também introduziu funções anônimas com o seguinte:
function { echo $1, $2; } foo bar
ou
(){ echo $1, $2; } foo bar
sintaxe, em que $0
se torna (anon)
(ou fica com o nome do script com set +o functionargzero
, como quando em sh
/ ksh
emulation).
Em zsh
, como em csh
, os argumentos dos scripts também estão na matriz $argv
, o que levanta a confusão sobre o nome do programa chamado de forma semelhante aos argumentos.
Lá, você pode atribuir valores aos parâmetros de posição com:
argv[1]=value
ou
1=value
(e também 0=newprogramname
para alterar o nome do programa).
Em outros shells semelhantes a Bourne, você precisa usar set
para atribuir todos de uma só vez:
set -- arg1 arg2
E você não pode alterar $0
.
Em rc
(pelo menos a porta Unix), você não pode fazer:
1 = value
Mas você pode fazer:
* = (arg1 arg2)
para definir os parâmetros posicionais. Você não pode alterar $0
em rc
, mas você pode em seu derivado es
com 0=newprogramname
como em zsh
.
TL; DR
O $1
, $2
... para se referir aos argumentos dos scripts vem do shell Thompson, mas ainda não foram chamados parâmetros posicionais . E $0
(provavelmente escolhido em referência a argv[0]
como @ikkachu bem colocado) refere-se ao nome do script.
O termo parâmetros posicionais vem do shell Bourne.
$0
não é um parâmetro posicional porque não se refere a um argumento do script. Refere-se ao nome do script (ou ao shell argv[0]
quando o shell não executa nenhum script).