Eu tenho um script simples em que o primeiro argumento é reservado para o nome do arquivo e todos os outros argumentos opcionais devem ser passados para outras partes do script.
Usando o Google, encontrei este wiki , mas ele forneceu um exemplo literal:
echo "${@: -1}"
Não consigo fazer mais nada funcionar, como:
echo "${@:2}"
ou
echo "${@:2,1}"
Eu recebo "Substituição ruim" do terminal.
Qual é o problema e como posso processar tudo, exceto o primeiro argumento passado para um script bash?
"{@:2}"
não trabalho, e é por isso que a resposta correta corresponde acima.Respostas:
Usa isto:
A seguinte sintaxe:
funcionaria tão bem, mas não é recomendado, porque, como o @Gordon já explicou, esse uso
*
executa todos os argumentos juntos como um único argumento com espaços, enquanto@
preserva as quebras entre eles (mesmo que alguns dos argumentos contenham espaços ) Não faz a diferençaecho
, mas é importante para muitos outros comandos.fonte
#!/usr/bin/env sh
é por isso que tive problemas. Você exemplo funciona bem, mesmo que acima fornecido, depois que eu removi que shebang"${@:2}"
vez disso - use*
executa todos os argumentos juntos como um único argumento com espaços, enquanto@
preserva as quebras entre eles (mesmo que alguns dos argumentos contenham espaços). A diferença não é perceptívelecho
, mas é importante para muitas outras coisas.echo
perdoa o suficiente para concatená-los para você; outros comandos podem não ser tão agradáveis. Não use apenas um ou outro: aprenda a diferença entre*
e@
e quando usar cada um. Você deveria usá-los igualmente. Um bom exemplo de quando isso será um problema: se$3
contiver uma quebra de linha (\n
), ela será substituída por um espaço, desde que você tenha uma$IFS
variável padrão .echo
apenas como exemplo - nesse caso, eles não devem ser executados juntos. Na minha experiência, as situações em que você deseja que elas funcionem juntas são raras (veja esta pergunta em um exemplo ) e"$@"
quase sempre é o que você deseja. Além disso, o problema mencionado com uma quebra de linha ocorre apenas se$@
(ou$*
) não estiver entre aspas duplas.$*
bastante nos meus scripts.Se você deseja uma solução que também funcione na
/bin/sh
tentativashift [n]
muda os parâmetros posicionais n vezes. Ashift
define o valor de$1
para o valor de$2
, o valor de$2
para o valor de$3
, e assim por diante, diminuindo o valor de$#
um.fonte
foo=shift
, não faz o que eu esperava.foo=$(shift)
shift
(no shell) não tem saída. Apenas descarta$1
e muda tudo para baixo. 2)$(...)
inicia um subshell, que possui seus próprios argumentos locais. Ela muda os argumentos no subnível, que não afeta o paisomecommand "$1" "${@:2}"
faz com este método (ou seja, shift "inline")?http://wiki.bash-hackers.org/scripting/posparams
Explica o uso de
shift
(se você deseja descartar os primeiros N parâmetros) e, em seguida, implementar o Uso em Massafonte
Deparei com isso procurando algo mais. Embora o post pareça bastante antigo, a solução mais fácil no bash é ilustrada abaixo (pelo menos o bash 4) usando
set -- "${@:#}"
onde # é o número inicial do elemento do array que queremos preservar adiante:Basicamente, o
set -- "${@:3}"
just aparece os dois primeiros elementos da matriz como shift do perl e preserva todos os elementos restantes, incluindo o terceiro. Eu suspeito que há uma maneira de destacar os últimos elementos também.fonte