O que "while test $# -gt 0" faz?

O que "while test $# -gt 0" faz?

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 parametersfor maior que 0).

o shiftcomando 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á shiftno corpo do loop while.

$1==> representa sempre o primeiro parâmetro

Para tornar isso mais concreto, digamos que você esteja passando parâmetros ae .bc

$1==> representa acomo este é o seu primeiro parâmetro

chamando now shift, adesaparece e sua lista de parâmetros é agora be, cportanto, se você invocar $1agora, é bporque este é agora o primeiro parâmetro da lista. Invocar shiftmais uma vez sua lista de parâmetros agora é apenas c, portanto $1é agora c. Chamar shiftmais 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 shifte 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 $1isso significa o cabeçalho do lista de parâmetros. Ao shifting 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.she 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 whileloop 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_CHKdeve ser salvar informações que você considera valiosas de uma forma ou de outra.

_fnse comportaria da mesma forma se seu conteúdo fosse o corpo de um script ou como está na forma de uma função shell.

_fnidentifica stdin- neste caso, "arg2" echoed sobre |pipe- na primeira linha, definindo setseu 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 $1O primeiro parâmetro é ${set+}substituir o interno do shell :truepara satisfazer a whilecondicional do loop. Assim que $1não for definido que a substituição não aconteça, a condicional será avaliada como falsee o whileloop será interrompido.

Para cada iteração do whileloop, o _fn() echoes é seu $1primeiro parâmetro &&se for bem-sucedido ( echoésemprebem-sucedido) [ tests ]para ver se é $1igual à string "arg2" &&se [ test ]for bem-sucedido _fn() echoes $1novamente.

$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 whileloop, shifteliminamos o $1primeiro parâmetro. Então na iteração 1 "$@"fica assim:

arg1 arg2

Mas depois da shiftprimeira vez parece:

arg2

E depois shiftda última vez parece:

Então, isso nos traz de volta para ${1+:} false- porque $1agora está desativado, o shell não será substituído :truee, em vez disso, apenas falseserá avaliado, o que interrompe o whileloop e encerra o_fn().

informação relacionada