Compreendendo os operadores booleanos no script bash [duplicado]

Esta pergunta já tem respostas aqui :

Resposta

A variável $phone_missing é uma string que contém false. E uma string não vazia avalia para true. Veja também http://www.linuxintro.org/wiki/Babe#empty_strings

Comentários

  • Ah, certo. Eu teria declarado essa variável como booleana (pelo menos não com a palavra de declaração), mas o console do ash ' não permitiu. Eu também não ' não quero comparar Strings. Como isso é feito da maneira certa?
  • stackoverflow.com/questions/2953646/… , mas tome cuidado: esse cara EXECUTA uma variável de string, e tanto falso quanto verdadeiro são comandos unix.

Resposta

Costumo usar “verdadeiro” e “falso”, pois também são comandos que apenas retornam sucesso e falha, respectivamente. Então você pode fazer

if "$phone_missing"; then ... 

Resposta

Aqui está uma maneira de fazer isso, mantendo os valores verdadeiro / falso.

 phone_missing=false if [ "$phone_missing" != false ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi if [ "$phone_missing" == true ]; then echo "phone_missing is true." fi  

As aspas duplas ao redor $phone_missing são para proteger contra o caso em que a variável phone_missing não está definida. Outro idioma comum para evitar isso é [ x$phone_missing != xfalse ], mas as aspas parecem mais naturais para mim.

A dica está na bash página de ajuda de test:

 STRING True if string is not empty. ... ! EXPR True if expr is false. 

Então, basicamente [ $foo ] será verdadeiro se $foo for não vazio. Nem verdadeiro ou falso, apenas não vazio. [ ! $foo ] é verdadeiro se $ foo estiver vazio ou indefinido.

Você sempre pode alterar seu código para apenas definir phone_missing como não -valor vazio e, que denotará verdadeiro. Se phone_missing não estiver definido (ou vazio – phone_missing=""), será falso. Caso contrário, você deve usar os operadores de teste de string (= e !=).

O outro pequeno problema é A atribuição. Você o tem como $phone_missing=true, mas deve ser phone_missing=true (sem cifrão).

Desculpe se este for um pouco denso, é porque eu sou. Foi um longo dia. 🙂

Resposta

Outras respostas forneceram a solução, mas explicarei o que havia de errado com o pensamento original.

Variáveis Bash não possuem tipos, então não existe algo como uma variável booleana ou valor como verdadeiro ou falso. Basicamente todas as variáveis bash são apenas strings.

Quando você testa uma variável / string no bash sem especificar o tipo de teste (-n ou -z), o padrão será um teste -n (string de comprimento diferente de zero).

Portanto, [ "$var" ] é equivalente a [ -n "$var" ]. Contanto que $var contenha pelo menos 1 caractere, foi avaliado como verdadeiro.

Como você negou a expressão, [ ! "$var" ] é equivalente a [ ! -n "$var" ]. Portanto, se $var contém pelo menos 1 caractere, a expressão é falsa.

Desde false (que é apenas uma string) contém 5 caracteres, a expressão é falsa. Se não importa qual string você definir phone_missing como (true, 0, 1), a expressão sempre será false porque phone_missing tem comprimento diferente de zero. A única maneira de torná-lo true é phone_missing="" já que é comprimento zero.

Resposta

Não use string para booleano. Use número inteiro.

Entrada:

val=1 ((val)) && echo "true" || echo "false" val=0 ((val)) && echo "true" || echo "false" 

Saída:

true false 

Fonte :

((expressão))

A expressão é avaliada de acordo com as regras descritas abaixo em AVALIAÇÃO ARITMÉTICA. Se o valor da expressão for diferente de zero, o status de retorno será 0; caso contrário, o status de retorno é 1. Isso é exatamente equivalente a let “expression”.

Resposta

Eu teria feito isso como um comentário para apoiar James Ko, mas não tinha representante para comentar ou votar publicamente.

O problema aqui é que os [] colchetes são notações para fazer um teste de comparação, como valor ou igualdade de string.

A veracidade da string em bash para uma string vazia é "" (string vazia) avalia como falsa (valor de retorno 1) e qualquer string não vazia “false” “true “ou” bob “s seu tio” avalia como verdadeiro (valor de retorno 0).

Você pode provar isso para si mesmo com:

 if [ "foo" ]; then echo true is $?; else echo false is $?; fi 

O $? acima é uma variável especial que contém o último status de saída dos comandos (0 sucesso e qualquer> 0 para código de erro) e produzirá true is 0. Você pode substituir "foo" por qualquer coisa que desejar e o resultado será o mesmo, exceto se você substituí-lo por uma string vazia "" ou "", caso em que avaliará a condição else e produzirá false is 1.

Ao usar o [ ] coloca entre parênteses a declaração interna como! $ phone_missing é avaliada e retorna um 0 para verdadeiro ou 1 para falso para o controle if l declaração. Uma vez que o colchete avalia as comparações de string e valor, o $ phone_missing é primeiro expandido para a string não vazia “false” que é avaliada por [] como string não vazia (ou true) e então o! inverte o resultado que resulta na instrução if obtendo um falso (ou valor de retorno 1) e pula o corpo condicional executando a instrução else, se presente.

Como James Ko disse, a notação seria apenas passar o variável que mantém seu “booleano” para a instrução de controle if. Nota que em bash um booleano verdadeiro e falso devem estar em minúsculas como em: bool_true = true bool_false = falso Qualquer outro caso será avalie como strings e não booleanas.

Então, usando seu exemplo e a resposta de James Ko, seria:

phone_missing=false echo "missing $phone_missing" if ! $phone_missing then echo "Lost phone at $readabletime" $phone_missing=true fi 

ou como I prefira para legibilidade (sintaticamente o mesmo e James Ko “s)

phone_missing=false echo "missing $phone_missing" if ( ! $phone_missing ); then echo "Lost phone at $readabletime" $phone_missing=true fi 

Outras respostas, como a de Alexios, estão literalmente verificando o conteúdo da string. Assim, qualquer uma das seguintes opções resultaria em falso:

phone_missing=false if [ "$phone_missing" != false ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi if [ "$phone_missing" == true ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi if [ "$phone_missing" == Bobs_your_uncle ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi 

Resposta

A sintaxe correta é if ! $bool; then [statements]; fi.

Exemplo:

bool=false if ! $bool; then echo "This is correct!" fi if [ ! $bool ]; then echo "This is wrong!" fi 

Resultado: This is correct!

Comentários

  • Há um fundo de verdade em sua resposta, mas, sem qualquer explicação, causa mais confusão do que remediar. Além disso, é pouco mais do que uma repetição de uma das respostas anteriores. Se você não deseja que sua resposta seja removida, explique por que está certa.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *