Estou escrevendo um script de shell e preciso imprimir o enésimo argumento do script.
Por exemplo, suponha que temos n=3
e nosso script é executado com argumentos suficientes. Agora eu preciso imprimir o n
argumento th, ou seja $3
.
Mas se n=2
, imprimiríamos o argumento $2
.
Eu não quero usar if
declarações. Eu queria fazer algo como
echo $($n)
mas o acima não funciona do jeito que eu preciso.
Por ordem cronológica, em várias conchas:
$argv[$n]
(também funciona em zsh desde 1991 e fish desde 2005)$argv[n]
/$@[n]
/$*[n]
(o último também suportado pelo yash, mas apenas com chaves extras:${@[n]}
/${*[n]}
)$$n
/$*($n)
(também funciona em es, akanga)${@:n:1}
,${*:n:1}
(também suportado por bash desde 1996; zsh também desde 2010 , embora você precise${@:$n:1}
ou esteja${@: n:1}
lá para evitar conflitos com modificadores de estilo csh e veja lá sobre o"$*"
caso)${!n}
${(P)n}
.Lembre-se que em ksh93/bash/yash, você precisa citar expansões de parâmetros em contextos de lista pelo menos, e csh dificilmente pode ser usado para escrever código confiável.
Em
bash
, há uma diferença entre"${!n}"
e"${@:n:1}"
no contexto da lista quando o enésimo parâmetro posicional não é definido, pois o último se expande para nenhum argumento enquanto o primeiro se expande para um elemento vazio.Em shells do tipo Bourne (mas não no shell Bourne, onde isso não funcionará para índices após o dia 9), e com a sintaxe POSIX sh padrão, você também pode fazer:
Haverá também diferenças de comportamento entre todos aqueles se
$n
não contiver a representação decimal canônica de um número inteiro estritamente maior que 0. Se você não puder garantir que será o caso, usar a maioria deles (não apenaseval
um) seria introduzir uma vulnerabilidade de execução de comandos arbitrários (as únicas exceções são comrc
e talvezcsh
acima).Lembre-se também que, exceto em
zsh
(comecho -E - $argv[n]
),yash
(comECHO_STYLE=raw echo "${*[$n]}"
) efish
(comecho -- $argv[$n]
), nãoecho
pode ser usado para gerar dados arbitrários, useprintf '%s\n' ...
).Os argumentos que você passa para um script são armazenados no
@
array, então a maneira simples de fazer o que você quer é pegar um array slice , começando em positionn
e tendo um comprimento de 1:Se você executar isso com alguns argumentos, obterá:
A outra alternativa, e o que você estava pedindo originalmente, é chamada de "expansão indireta":
Executando isso:
Você pode usar a indireção variável:
Solução de shell portátil simples (sem dependência de bash) (módulo potencial de maldade do
echo
comando; pode ser substituído porprintf
):Então faça: