O que “while test $ # -gt 0” faz?

5

Estou tentando criar uma função e acredito que encontrei um bom exemplo de trabalho, mas não entendo toda a lógica por trás dela.

Mais especificamente, na linha "while", alguém poderia explicar o que o teste é e faz? o que é $ # (não é # um caractere de comentário?) e o parâmetro -gt 0 vem? não consegui encontrá-lo na página man while.

Aqui está o exemplo:

function my_function()
{
while test $# -gt 0
do
    $
echo "$1"
    shift
done
}

Obrigado.

    
por TCZ8 07.05.2014 / 00:27

4 respostas

9

Embora # seja definitivamente um comentário, $# contém o número de parâmetros passados para sua função.

test é um programa que permite executar vários testes, por exemplo, se um número for maior que outro número (se a sua operadora for -gt ; há muitos outros operadores, consulte man test ). Ele retornará o sucesso se o teste for bem-sucedido (nesse caso, se the number of parameters IS for maior que 0).

o comando shift joga fora o primeiro parâmetro. Também diminui $#

O código como um todo pode ser visto como: faça algo com um parâmetro (neste caso, mostrando-o na tela), então descarte-o; 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 $@

    
por 07.05.2014 / 00:34
2

$# == > parâmetros de script passados

test == > comando de avaliação de condição

-gt == > representa maior que

test a -gt b == > true se a for maior que b, falso caso contrário

Colocando tudo junto:

while test $# -gt 0 == > enquanto há mais parâmetros passados (a razão pela qual isso está mudando é por causa da mudança)

O que torna as coisas complicadas é shift no corpo do loop while.

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

Para tornar isso mais concreto, digamos que você esteja passando os parâmetros a , b e c .

$1 == > representa a porque este é seu primeiro parâmetro

chamando agora shift , a desapareceu e sua lista de parâmetros agora é b e c , se você invocar $1 , agora é b , pois agora é o primeiro parâmetro na lista . Invocando 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 (como a lista de parâmetros, se não maior que 0, já que agora é zero), o que fará com que o loop while termine.

Quais são os ganhos de usar shift e referindo-se ao parâmetro atual como $1 ?

Ele dá a você a flexibilidade de não saber com antecedência em seu script quantos parâmetros são passados no script e, independentemente disso, iterá-los um por um referindo-se dentro do loop while ao parâmetro atual sempre como $1 desde isso significa o chefe da lista de parâmetros. Por shift ing eventualmente, a lista de parâmetros estará vazia, portanto, é importante ter a condição while para verificar se ela é maior que zero para finalizar e não infinitamente loopar.

    
por 07.05.2014 / 00:58
1

Execute o script abaixo para entender o que as variáveis significam. Salve o script como somescript.sh e chame o script 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: $@"
    
por 07.05.2014 / 00:38
0

Se você me perdoar um pouco de reciclagem de respostas, eu acho que você pode achar isso útil.

_fn() { set -- "$@" $(cat)
    while ${1+:} false ; do 
        echo "$1" && [ "$1" = "arg2" ] && echo "$1"
        $YOUR_CHK
        shift
    done
}

echo "arg2" | _fn "arg1"

OUTPUT

arg1
arg2
arg2

Que lida com os argumentos de linha de cmd e stdin . Ele só executa o loop while para verificá-los enquanto você ainda tem pelo menos um argumento salvo em sua matriz de parâmetros. Ele descarta todos os argumentos verificados, portanto, parte do $YOUR_CHK deve estar salvando as 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 se estivesse na forma de uma função de shell.

_fn processa stdin - nesse caso "arg2" echo ed sobre o |pipe - na primeira linha por set seu array de parâmetro posicional $@ array para tudo que é passado na linha de comando - ou "$@" - E tudo cat é enviado via $(comand substitution) .

O

while _fn's $1 primeiro parâmetro é ${set+} , substituímos o :true do shell para satisfazer o condicional while do loop. Assim que $1 não estiver certo de que a substituição não ocorre, a condicional será avaliada como false e o while será interrompido.

Para cada iteração do loop while , o _fn() echo es seu $1 primeiro parâmetro && se for bem-sucedido ( echo é sempre com êxito) [ tests ] para ver se $1 é igual à string "arg2" && se o [ test ] for bem-sucedido _fn() echo es $1 novamente.

$YOUR_CHK é um null-op - é uma variável indefinida que nada avalia antes mesmo de o shell executar qualquer código.

Para cada iteração do loop while , nós shift descartamos o primeiro parâmetro $1 . Então, na iteração, 1 "$@" se parece com:

arg1 arg2

Mas depois de shift , a primeira vez parece:

arg2

E depois nós shift da última vez que parece:

Então, isso nos traz de volta novamente para ${1+:} false - porque $1 agora está desanexado, o shell não substituirá :true e, em vez disso, apenas false é avaliado, que quebra o loop while e termina o _fn().

    
por 07.05.2014 / 07:47