Estou tentando criar uma função e acredito que encontrei um bom exemplo funcional, mas não entendo toda a lógica por trás disso.
Mais especificamente, na linha “while”, alguém poderia explicar o que é o teste e o que faz? o que é $# (# não é um caractere de comentário?) e de onde vem o parâmetro -gt 0? não consegui encontrá-lo na página de manual while.
Aqui está o exemplo:
function my_function()
{
while test $# -gt 0
do
$
echo "$1"
shift
done
}
Obrigado.
Responder1
Embora #
por si só seja definitivamente um comentário, $#
contém o número de parâmetros passados para sua função.
test
é um programa que permite realizar vários testes, por exemplo, se um número é maior que outro número (se o seu operador for -gt
; existem muitos outros operadores, veja man test
). Ele retornará sucesso se o teste for bem-sucedido (neste caso, se the number of parameters
for maior que 0).
o shift
comando descarta o primeiro parâmetro. Também diminui$#
O código como um todo pode ser visto como: fazer algo com um parâmetro (no caso, mostrá-lo na tela), depois descartá-lo; repita até que não haja mais parâmetros.
Se você quiser ver todos os parâmetros restantes, úteis para depuração, verifique o conteúdo de$@
Responder2
$#
==> parâmetros de script passados
test
==> comando de avaliação de condição
-gt
==> representaMaior que
test a -gt b
==> verdadeiro se a for maior que b, falso caso contrário
Juntando tudo:
while test $# -gt 0
==> enquanto houver mais parâmetros passados (a razão pela qual isso está mudando é por causa da mudança)
O que torna as coisas complicadas está shift
no corpo do loop while.
$1
==> representa sempre o primeiro parâmetro
Para tornar isso mais concreto, digamos que você esteja passando parâmetros a
e .b
c
$1
==> representa a
como este é o seu primeiro parâmetro
chamando now shift
, a
desaparece e sua lista de parâmetros é agora b
e, c
portanto, se você invocar $1
agora, é b
porque este é agora o primeiro parâmetro da lista. Invocar shift
mais uma vez sua lista de parâmetros agora é apenas c
, portanto $1
é agora c
. Chamar shift
mais uma vez deixa a lista de parâmetros vazia, portanto, a condição while não terá sucesso (já que a lista de parâmetros não é mais maior que 0, pois agora tem tamanho zero), o que fará com que o loop while termine.
Quais são os ganhos de usar shift
e referir-se ao parâmetro atual como $1
?
Dá a você a flexibilidade de não saber antecipadamente em seu script quantos parâmetros são passados no script e, independentemente disso, iterar através deles um por um referindo-se dentro do loop while ao parâmetro atual sempre, pois $1
isso significa o cabeçalho do lista de parâmetros. Ao shift
ing eventualmente a lista de parâmetros ficará vazia, portanto é importante ter a condição while para verificar se é maior que zero para encerrar e não fazer um loop infinito.
Responder3
Execute o script abaixo para entender o que as variáveis significam. Salve o script como somescript.sh
e chame-o com alguns parâmetros de entrada.
#!/bin/bash
echo "I display the total parameters passed to this script from commandline"
echo $#
echo "I display all the parameter values"
echo "Input: $@"
echo "I display the first parameter value"
echo "$1"
shift
echo "After shift: $@"
Responder4
Se você me perdoar um pouco pela reciclagem de respostas, acho que isso pode ser útil.
_fn() { set -- "$@" $(cat)
while ${1+:} false ; do
echo "$1" && [ "$1" = "arg2" ] && echo "$1"
$YOUR_CHK
shift
done
}
echo "arg2" | _fn "arg1"
SAÍDA
arg1
arg2
arg2
Isso lida com argumentos de linha cmd e stdin
. Ele apenas executa o while
loop para verificá-los enquanto você ainda tem pelo menos um argumento salvo em sua matriz de parâmetros. Ele descarta todos os argumentos que verifica, portanto, parte disso $YOUR_CHK
deve ser salvar informações que você considera valiosas de uma forma ou de outra.
_fn
se comportaria da mesma forma se seu conteúdo fosse o corpo de um script ou como está na forma de uma função shell.
_fn
identifica stdin
- neste caso, "arg2" echo
ed sobre |pipe
- na primeira linha, definindo set
seu array de shell de parâmetro posicional $@
para tudo passado na linha de comando - ou "$@"
- AND tudo cat
é cuspido via $(comand substitution)
.
while _fn's $1
O primeiro parâmetro é ${set+}
substituir o interno do shell :true
para satisfazer a while
condicional do loop. Assim que $1
não for definido que a substituição não aconteça, a condicional será avaliada como false
e o while
loop será interrompido.
Para cada iteração do while
loop, o _fn() echo
es é seu $1
primeiro parâmetro &&
se for bem-sucedido ( echo
ésemprebem-sucedido) [ tests ]
para ver se é $1
igual à string "arg2"
&&
se [ test ]
for bem-sucedido _fn() echo
es $1
novamente.
$YOUR_CHK
é uma operação nula - é uma variável não definida que não é avaliada antes que o shell execute qualquer código.
Para cada iteração do while
loop, shift
eliminamos o $1
primeiro parâmetro. Então na iteração 1 "$@"
fica assim:
arg1 arg2
Mas depois da shift
primeira vez parece:
arg2
E depois shift
da última vez parece:
Então, isso nos traz de volta para ${1+:} false
- porque $1
agora está desativado, o shell não será substituído :true
e, em vez disso, apenas false
será avaliado, o que interrompe o while
loop e encerra o_fn().