Por que $ {$ #} retorna o mesmo resultado que $$ no shell?

18

Ao tentar obter o último parâmetro posicional definido /bin/dash, tentei echo ${$#}. Surpreendentemente, isso não resultou em um erro, mas no PID, que é o mesmo que o $$conteúdo da variável. Pergunta, é por que essa sintaxe funcionou? Qual é a regra de sintaxe que o shell aplicou aqui?

Basicamente, o que eu fiz é

$ set 1 2 3 4 5
$ echo ${$#}
13819
$ echo $$
13819

Aparentemente, o %personagem também é ignorado nesse construto

$ echo ${$%}
13819

Mas *e @resultar em erro de substituição incorreto:

$ echo ${$*}
sh: 10: Bad substitution
$ echo ${$@}
sh: 11: Bad substitution
Sergiy Kolodyazhnyy
fonte
3
O que você está esperando ${$*}e ${$@}produzir?
Kusalananda
2
@Kusalananda Sem expectativas. Eu estava tentando outros personagens ao lado #e %e qual comportamento resultados daqueles.
Sergiy Kolodyazhnyy
11
Para fazer indiretamente o Dash, use eval, por exemplo dash -c 'set 1 2 3 4 5; eval "echo \$$#"'. Fonte: Ubuntu Wiki
wjandrea
11
@wjandrea Sim, já está ciente disso. Na verdade, já existe uma pergunta sobre isso: stackoverflow.com/questions/1853946/… Eu estava tentando encontrar um método sozinho sem ler a pergunta primeiro (e eu já sabia o for i; do true; doneque era o último item $i), mas estava procurando algo mais elegante. evalé claro que pode haver problemas em potencial, pensados ​​até que ponto - esse é outro tópico. Mas sim, é uma opção
Sergiy Kolodyazhnyy

Respostas:

35

Isso ocorre $$ com um prefixo vazio removido :

${parameter#[word]}

Remova o menor padrão de prefixo . A palavra deve ser expandida para produzir um padrão. A expansão do parâmetro resultará em parâmetro , com a menor porção do prefixo correspondida pelo padrão excluída. Se presente, a palavra não começará com aspas #.

O mesmo se aplica a %(sufixo). @e *não são modificadores de expansão de parâmetro, portanto, são erros. Isso iria acontecer para $?, $-ou uma hipotética $=também. ${$+}é uma expansão vazia.

Michael Homer
fonte
Eu deveria ter reconhecido a substituição de parâmetros imediatamente lá. Boa pegada.
Sergiy Kolodyazhnyy