Estou escrevendo um script muito simples que chama outro script e preciso propagar os parâmetros do meu script atual para o script que estou executando.
Por exemplo, meu nome de script é foo.sh
e chamabar.sh
foo.sh:
bar $1 $2 $3 $4
Como posso fazer isso sem especificar explicitamente cada parâmetro?
bash
command-line-arguments
Fragsworth
fonte
fonte
Respostas:
Use em
"$@"
vez de simples$@
se você realmente deseja que seus parâmetros sejam passados da mesma forma.Observar:
fonte
'arg with spaces'
para os três exemplos também. Fiquei surpreso com os resultados; espero que você possa explicá-los../foo.sh "arg with spaces"
e./foo.sh 'arg with spaces'
são 100% idênticos, então não vejo como a sugestão de adicioná-lo aos exemplos dados seria de alguma ajuda.Para bash e outras conchas do tipo Bourne:
fonte
$argv:q
funcione em algumas variantes do csh.exec java com.myserver.Program "$@"
Isso faz com que o bash seja executado em java, em vez de esperar que ele seja concluído. Então, você está usando um slot de processo a menos. Além disso, se o processo pai (que executou o seu script) o estiver assistindo via pid, e esperando que seja o processo 'java', algumas coisas incomuns poderão ser quebradas se você não executar um exec; o exec faz com que o java herde o mesmo pid.args=("$@")
e expandir cada elemento como uma “palavra” separado shell ( semelhante a"$@"
) com"${args[@]}"
."$@"
, como falhará se você tiver escapado de espaços em um argumento, caracteres nulos ou outros caracteres especiais?Use
"$@"
(funciona para todos os compatíveis com POSIX ).Do Bash por exemplo .
fonte
$*
. Eu acredito que há progressão histórica aqui;$*
não funcionou como planejado, por isso$@
foi inventado para substituí-lo; mas as regras de citação são o que são, as aspas duplas ainda são necessárias (ou serão revertidas para a$*
semântica quebrada ).echo "$@"
as./script.sh a "b c" d
, é só pegar ema b c d
vez dea "b c" d
, o que é muito diferente.echo
recebe três argumentos:"a" "b c" "d"
(então o shell os une como parte de sua expansão de string). Mas se você tivesse usadofor i in "$@"; do echo $i; done
Você teria conseguidoa⏎b c⏎d
.Sei que isso foi bem respondido, mas aqui está uma comparação entre "$ @" $ @ "$ *" e $ *
Conteúdo do script de teste:
Agora, execute o script de teste com vários argumentos:
fonte
Apenas pensei que isso poderia ser um pouco mais útil ao tentar testar como os argumentos de args entram em seu script
fonte
$#
""
,''
como argumento, também se não houver argumentos, é silencioso. Eu tentei consertar isso, mas precisa de um loop for e counter com$#
. Acabei de adicionar isso no final:echo "End of args or received quoted null"
Meu SUN Unix tem muitas limitações, mesmo "$ @" não foi interpretado como desejado. Minha solução alternativa é $ {@}. Por exemplo,
A propósito, eu tinha que ter esse script em particular porque meu Unix também não suporta grep -r
fonte
ksh
Se você incluir
$@
em uma sequência de caracteres citada com outros caracteres, o comportamento será muito estranho quando houver vários argumentos, apenas o primeiro argumento será incluído dentro das aspas.Exemplo:
Rendimentos:
Mas atribuindo a uma variável diferente primeiro:
Rendimentos:
fonte
"$@"
bash. Também ajuda a ilustrar a principal diferença entre$@
e$*
e por que os dois são úteis. Nabash(1)
seção Parâmetros especiais da página de manual: "*
- Quando a expansão ocorre entre aspas duplas, ela se expande para uma única palavra com o valor de cada parâmetro [...] Ou seja,"$*"
é equivalente a"$1c$2c..."
, ondec
está [$IFS
]." E, de fato, usar em$*
vez de$@
no seu primeiro exemplo teria gerado uma saída idêntica à segunda versão."$@"
. Novamente na página do manual: "@
- Quando a expansão ocorre entre aspas duplas, cada parâmetro se expande para uma palavra separada. Ou seja,"$@"
é equivalente a"$1"
"$2"
... Se a expansão entre aspas duplas ocorrer dentro de uma palavra, a expansão do primeiro parâmetro será unida com a parte inicial da palavra original e a expansão do último parâmetro é associada à última parte da palavra original. " ... E, de fato, se o seu código estiverbash -c "true foo $@ bar baz"
, execute-o comotest.sh one two
seria líquidobash -c 'true foo one' 'two bar baz'
.$*
, parece que esqueço que ele existe. #$@
estava ganhando força quando comecei o script de shell, ainda preciso me lembrar de que está lá. Era comum ver"$*"
usado em scripts ... então o autor percebia que estava quebrando todos os argumentos juntos, para que tentassem todo tipo de bobagem complexa com a divisão de palavras"$*"
ou [re] montando uma lista de argumentos fazendo um loop sobreshift
a puxá-los um por um ... apenas usando$@
resolve. (Ajuda a que o bash usa o mesmo mnemônico para os membros da matriz de acesso, também:${var[*]}
para todos eles como uma palavra,${var[@]}
para uma lista de palavras.)bash -c
de uma maneira que não faz absolutamente nenhum sentido.Às vezes, você deseja passar todos os seus argumentos, mas precedido por uma bandeira (por exemplo
--flag
)Você pode fazer isso da seguinte maneira:
Nota: para evitar a divisão extra do campo, é necessário citar
%s
e$@
, e para evitar ter uma única sequência, não é possível citar o subshell deprintf
.fonte
Funciona bem, exceto se você tiver espaços ou caracteres de escape. Não encontro uma maneira de capturar argumentos neste caso e enviar para um ssh dentro do script.
Isso pode ser útil, mas é tão feio
fonte
Muitas respostas aqui recomendam
$@
ou$*
com e sem aspas, no entanto, nenhuma parece explicar o que elas realmente fazem e por que você deveria fazer isso. Então, deixe-me roubar este excelente resumo desta resposta :Observe que as aspas fazem toda a diferença e, sem as duas, têm um comportamento idêntico.
Para o meu propósito, eu precisava passar parâmetros de um script para outro como está e, para isso, a melhor opção é:
Observe sem aspas e
$@
deve funcionar bem na situação acima.fonte
bar "$@"
será equivalente abar "$1" "$2" "$3" "$4"
Observe que as aspas são importantes!
"$@"
,$@
,"$*"
Ou$*
vai cada comportam um pouco diferente em relação escapar e concatenação como descrito nesta resposta stackoverflow .Um caso de uso estreitamente relacionado está passando todos os argumentos fornecidos dentro de um argumento como este:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\""
.Eu uso uma variação da resposta do @ kvantour para conseguir isso:
bash -c "bar $(printf -- '"%s" ' "$@")"
fonte