Instrução test [RESOLVIDO]

1. Instrução test [RESOLVIDO]

Éder
edertux

(usa Debian)

Enviado em 16/07/2013 - 17:49h

Olá pessoal!

Segundo todas as vias de informação, test -n verifica se a variável é diferente de zero.
Porém no script abaixo se eu apenas teclar "Enter" sem digitar nada, ele printa "Olá , tudo bem?" ao invés de "Você não digitou seu nome. Script encerrado!"

--

#!/bin/bash

echo "Digite seu nome..."

read NOME

if [ -n $NOME ] ; then

echo "Olá $NOME, tudo bem?"

else

echo "Você não digitou seu nome. Script encerrado!"

fi

--

Alguém sabe solucionar esse mistério?




  


2. Re: Instrução test [RESOLVIDO]

Fernando
phoemur

(usa Debian)

Enviado em 16/07/2013 - 20:49h

man test

NAME
test - check file types and compare values
(...)
-n STRING
the length of STRING is nonzero
(...)


Ou seja, não tem nada de estranho no comportamento do seu script, pois quando dá enter o enter também fica gravado na sua string, ou seja, ela não está vazia...



3. Re: Instrução test [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 16/07/2013 - 21:34h

O que se disse acima sobre o Enter ficar gravado na variável não é correto. Não fica.

A forma correta de fazer é colocar a avaliação da variável entre aspas, ou seja:

if [ -n "$NAME" ]; ... 


Isso é válido sempre que você quiser passar o valor de uma variável a um comando externo, porque o shell primeiro expande a variável, e depois chama o comando com o valor já expandido. Desse modo, se a variável não tiver valor definido, ou se esse valor estiver vazio, ou se o valor contiver espaços, a quantidade de argumentos passada ao programa pode variar bastante.

Aliás, veio-me à cabeça um exemplo interessante. Imagine o seguinte script.

#!/bin/sh

echo -n "Digite o nome do arquivo a apagar: "
read arq
if rm $arq; then
echo "Arquivo apagado com sucesso."
exit 0
fi
echo "Não foi possivel apagar o arquivo." >&2
exit 1


Agora imagine que alguém que executou o script, ao ser peguntado do nome do arquivo a apagar, digitou "-Rf /". Na linha seguinte à leitura, vai-se executar um comando que vai tentar remover todos os arquivos do sistema.

Há forma melhores de consertar o script, mas se simplesmente colocássemos ``rm "$arq"´´ em lugar de ``rm $arq´´ o script já não faria a bobagem de antes, mesmo se o usuário resolvesse tentar alguma gracinha.

Regra de ouro: sempre que importar se o valor de uma variável é nulo ou contém espaços, só expanda tal variável entre aspas.


4. Re: Instrução test [RESOLVIDO]

Fernando
phoemur

(usa Debian)

Enviado em 16/07/2013 - 22:21h

Valeu pela explicação Paulo
Eu tive a intuição de que talvez fosse como em C/C++, em que as strings têem que terminar com o caracter nulo.
Não poderia estar mais errado...


5. Re: Instrução test [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 17/07/2013 - 10:37h

phoemur escreveu:

Valeu pela explicação Paulo
Eu tive a intuição de que talvez fosse como em C/C++, em que as strings têem que terminar com o caracter nulo.
Não poderia estar mais errado...


Não foi um engano tão terrível. Mas é melhor separar os contextos sempre.

test/[ é mesmo um comando um pouco complicado. O caso em questão é que quando o comando é invocado com um argumento só, o comando verifica se o tamanho do argumento é zero. Desse modo,

[ -n ] 


é equivalente a

[ -n "-n" ] 



Mas isso só se sabe lendo a documentação. Eu mesmo não sabia, fiquei sabendo agora, quando li a documentação por causa deste tópico.


6. Re: Instrução test [RESOLVIDO]

Éder
edertux

(usa Debian)

Enviado em 17/07/2013 - 13:16h

phoemur escreveu:

man test

NAME
test - check file types and compare values
(...)
-n STRING
the length of STRING is nonzero
(...)


Ou seja, não tem nada de estranho no comportamento do seu script, pois quando dá enter o enter também fica gravado na sua string, ou seja, ela não está vazia...


Olá phoemur!

Em primeiro lugar quero agradecer sua participação. Obrigado!

No entanto, a parte citada (ou qualquer outra) do man test não esclareceu minha dúvida mas, ajudou.
Ao final do manual tem a sugestão: info coreutils 'test invocation'. Ou simplesmente: info test.
Na seção 16.3.4 informa que para obter o retorno desejado é necessário expandir a variável, como o amigo paulo1205 informou anteriormente. Veja:

--

These options test string characteristics. You may need to quote
STRING arguments for the shell. For example:

test -n "$V"

The quotes here prevent the wrong arguments from being passed to
`test' if `$V' is empty or contains special characters.

`-z STRING'
True if the length of STRING is zero.

`-n STRING'
`STRING'
True if the length of STRING is nonzero.

--

Um abraço! ;-)


7. Re: Instrução test [RESOLVIDO]

Éder
edertux

(usa Debian)

Enviado em 17/07/2013 - 13:23h

paulo1205 escreveu:

O que se disse acima sobre o Enter ficar gravado na variável não é correto. Não fica.

A forma correta de fazer é colocar a avaliação da variável entre aspas, ou seja:

if [ -n "$NAME" ]; ... 


Isso é válido sempre que você quiser passar o valor de uma variável a um comando externo, porque o shell primeiro expande a variável, e depois chama o comando com o valor já expandido. Desse modo, se a variável não tiver valor definido, ou se esse valor estiver vazio, ou se o valor contiver espaços, a quantidade de argumentos passada ao programa pode variar bastante.

Aliás, veio-me à cabeça um exemplo interessante. Imagine o seguinte script.

#!/bin/sh

echo -n "Digite o nome do arquivo a apagar: "
read arq
if rm $arq; then
echo "Arquivo apagado com sucesso."
exit 0
fi
echo "Não foi possivel apagar o arquivo." >&2
exit 1


Agora imagine que alguém que executou o script, ao ser peguntado do nome do arquivo a apagar, digitou "-Rf /". Na linha seguinte à leitura, vai-se executar um comando que vai tentar remover todos os arquivos do sistema.

Há forma melhores de consertar o script, mas se simplesmente colocássemos ``rm "$arq"´´ em lugar de ``rm $arq´´ o script já não faria a bobagem de antes, mesmo se o usuário resolvesse tentar alguma gracinha.

Regra de ouro: sempre que importar se o valor de uma variável é nulo ou contém espaços, só expanda tal variável entre aspas.


Olá paulo1205!

Em primeiro lugar quero agradecer sua participação e, em segundo lugar, quero agradecer pelo esforço de matar a charada!
Era exatamente isso que eu tinha que fazer: expandir a variável.
Testei aqui e deu certíssimo!

Um abraço! ;-)


8. Agradecimento

Éder
edertux

(usa Debian)

Enviado em 17/07/2013 - 13:30h

Aos amigos phoemur e paulo1205:

Agradeço por me ajudarem.
Vocês são exemplos.
São pessoas como vocês que fazem a comunidade valer a pena.

Obrigado!

Abraços.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts