$#
é o número de argumentos, mas lembre-se de que será diferente em uma função.
$#
é o número de parâmetros posicionais passados para o script, shell ou função de shell . Isso ocorre porque, enquanto uma função shell está em execução, os parâmetros posicionais são substituídos temporariamente pelos argumentos da função . Isso permite que as funções aceitem e usem seus próprios parâmetros posicionais.
Esse script sempre imprime 3
, independentemente de quantos argumentos foram passados para o próprio script, porque "$#"
na função se f
expande para o número de argumentos passados para a função:
#!/bin/sh
f() {
echo "$#"
}
f a b c
Isso é importante porque significa que códigos como este não funcionam como você poderia esperar, se você não estiver familiarizado com o funcionamento dos parâmetros posicionais nas funções do shell:
#!/bin/sh
check_args() { # doesn't work!
if [ "$#" -ne 2 ]; then
printf '%s: error: need 2 arguments, got %d\n' "$0" "$#" >&2
exit 1
fi
}
# Maybe check some other things...
check_args
# Do other stuff...
Em check_args
, $#
expande para o número de argumentos passados para a própria função, que nesse script é sempre 0.
Se você quiser essa funcionalidade em uma função shell, precisará escrever algo assim:
#!/bin/sh
check_args() { # works -- the caller must pass the number of arguments received
if [ "$1" -ne 2 ]; then
printf '%s: error: need 2 arguments, got %d\n' "$0" "$1" >&2
exit 1
fi
}
# Maybe check some other things...
check_args "$#"
Isso funciona porque $#
é expandido fora da função e passado para a função como um de seus parâmetros posicionais. Dentro da função, $1
expande para o primeiro parâmetro posicional que foi passado para a função shell, em vez de para o script do qual faz parte.
Assim como $#
, os parâmetros especiais $1
, $2
etc., bem como $@
e $*
, também dizem respeito aos argumentos passados para uma função, quando são expandidas na função. No entanto, $0
se não mudar para o nome da função, que é por isso que eu ainda era capaz de usá-lo para produzir uma mensagem de erro qualidade.
$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3
Da mesma forma, se você definir uma função dentro de outra, estará trabalhando com os parâmetros posicionais passados para a função mais interna na qual a expansão é executada:
#!/bin/sh
outer() {
inner() {
printf 'inner() got %d arguments\n' "$#"
}
printf 'outer() got %d arguments\n' "$#"
inner x y z
}
printf 'script got %d arguments\n' "$#"
outer p q
Chamei esse script nested
e (após a execução chmod +x nested
) executei:
$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments
Sim eu conheço. "1 argumentos" é um erro de pluralização.
Os parâmetros posicionais também podem ser alterados.
Se você estiver escrevendo um script, os parâmetros posicionais fora de uma função serão os argumentos da linha de comando passados para o script, a menos que você os tenha alterado .
Uma maneira comum de alterá-los é com o shift
builtin, que desloca cada parâmetro posicional para a esquerda em um, descartando o primeiro e diminuindo $#
em 1:
#!/bin/sh
while [ "$#" -ne 0 ]; do
printf '%d argument(s) remaining.\nGot "%s".\n\n' "$#" "$1"
shift
done
$ ./do-shift foo bar baz # I named the script do-shift.
3 argument(s) remaining.
Got "foo".
2 argument(s) remaining.
Got "bar".
1 argument(s) remaining.
Got "baz".
Eles também podem ser alterados com o set
builtin:
#!/bin/sh
printf '%d args: %s\n' "$#" "$*"
set foo bar baz
printf '%d args: %s\n' "$#" "$*"
$ ./set-args a b c d e # I named the script set-args.
5 args: a b c d e
3 args: foo bar baz
$#
? O que você quer alcançar? Onde você conseguiu esse comando. Não é de todo relevante.