existe alguma maneira simples / limpa de fazer uma “variável booleana vazia” ser avaliada como 'falsa' em scripts bash?

1

Bem, a variável não é booleana até ser definida como true ou false .

Assim, quando o script começa, ele verifica se há um booleano ainda não definido como bTest='' . Então, se eu fizer isso: if $bTest;then echo "is active";fi ele irá mostrar "está ativo" quando eu quiser mostrar nada ...

Eu poderia usar isso: [ "$bTest" == true ] , quando antes era apenas $bTest , mas para mim esse é o problema, não é um "booleano", é uma comparação de string ...

Além disso, se eu errar o nome de uma variável booleana, ela ficará vazia e a execução do script não lançará nenhuma mensagem de erro ... e por várias vezes descobri que o problema real era apenas a variável equivocada ... ter isso? Eu uso gedit , então devo rastrear minhas falhas sozinho.

Gostaria de saber se existe uma maneira simples e limpa de trabalhar com booleanos em vez de digitar [ "$bTest" == true ] todas as vezes ..?

    
por Aquarius Power 02.02.2014 / 21:18

4 respostas

2

Com base na sua resposta, parece que você está realmente tentando evitar erros de digitação.

A melhor maneira de fazer isso é colocar

set -u

na parte superior do seu script de shell.

Então, em vez de um erro de digitação se expandindo para uma string vazia, é um erro fatal.

if $bTest; then
    echo "is active"
fi

# => is active

Versus

set -u
if $bTest; then
    echo "is active"
fi

# => typo.sh: line 4: bTest: unbound variable

Como alternativa, se você deseja atribuir padrões a variáveis, geralmente é melhor fazer todas as atribuições no topo do script da seguinte forma:

: ${bTest:=false}

Por fim, se você realmente quiser digitar um valor padrão toda vez, poderá usar

if ${bTest:-false}; then
    echo "is active"
fi
    
por 02.02.2014 / 23:03
2

A maneira mais simples é esta:

if ${bTest:?};then echo "is active";fi

Portanto, vou simplesmente de $bTest a ${bTest:?} e não preciso lidar com nada mais complexo como funções e aliases.

Tenha em mente que, como @samiam apontou, isso pode causar um problema para você se a variável estiver realmente configurada para algo e esse foi um comando como em bTest='ls -l';if ${bTest:?};then echo "is active";fi (onde ls -l será executado).

Mas no meu caso, eu trato todos os "booleanos" como booleanos, então eu só coloco true ou false neles; o maior problema que tenho tido com eles há anos são nomes de variáveis equivocadas; então eu sempre tenho um "booleano" vazio me incomodando até que descobri que eu estava errado ...

Portanto, se você usar seus "booleans" com outros valores que não sejam true ou false , não os use; como pode se tornar inseguro.

    
por 02.02.2014 / 21:38
1

O Bash não possui um tipo de dados booleano ( /bin/true e /bin/false são comandos que retornam 1 e 0, porque Bash, intuitivamente interpreta um código de retorno de 0 como 'tudo está bom' e qualquer outra coisa como 'houve um problema ')

De fato, o Bash não possui um tipo de dados numérico ( A=$(( $A + 1 )) converte $A em para um inteiro, adiciona um a ele e, em seguida, torna-o uma string novamente) e, mais precisamente, 0 não possui o mesmo valor da string vazia. BASH não é PHP (onde var_dump(0 == ""); retorna true).

Provavelmente, a melhor maneira de simular booleanos é a sugestão de aularon: Use o operador -z e considere strings vazias como falsas. por exemplo, [ ! -z "$bTest" ] && $bTest

Se isso não for limpo o suficiente para você, que tal ter as funções is_true e is_false ?

#!/bin/bash

is_true() {
        if [ "$1" = "false" ]; then
                return 1 # false
        fi
        if [ -z "$1" ]; then
                return 1 # false
        else
                return 0 # true
        fi
}

is_false() {
        if [ "$1" = "false" ]; then
                return 0 # true
        fi
        if [ -z "$1" ]; then
                return 0 # true
        else
                return 1 # false
        fi
}

A="1"
B=""

if is_true "$A" ; then
        echo A is true
else
        echo A is false
fi

if is_false "$A" ; then
        echo A is false
else
        echo A is true
fi

if is_true "$B" ; then
        echo B is true
else
        echo B is false
fi
    
por 02.02.2014 / 21:45
0

Shells convertem variáveis de ambiente em variáveis shell. Portanto, você nunca deve usar uma variável não inicializada como um ou outro dia seu script será interrompido porque, por um motivo ou outro, uma variável com o mesmo nome estava no ambiente que o shell recebeu na inicialização.

Então:

#! /bin/sh -
bTest=false

while getopts ...;
  ... ) bTest=true
done

if "$bTest"; then

(não esqueça as aspas, deixando de fora as aspas é o operador split + glob. Note que se $bTest estiver vazio, você receberá um erro sobre a string vazia não ser encontrada como um comando). / p>

Agora, se você quiser ignorar o aviso. Outra maneira de usar a sintaxe do ksh (também funciona em bash e zsh ) é usar expressões aritméticas e 1 ou qualquer valor diferente de zero para significar true.

0 e a string vazia significam false em expressões aritméticas.

Então você pode fazer:

#! /bin/bash -
while getopts ...;
  ... ) bTest=1
done
if ((bTest)); then...

Mas cuidado com o fato de seu script parar de funcionar se por algum motivo houver um bTest no ambiente (por exemplo, porque seu script é chamado de outro script que usa o mesmo nome de variável e o exportou (por exemplo,%)set -a ou porque é um script rc onde todas as variáveis estão no ambiente)).

    
por 02.02.2014 / 23:55

Tags