Estive aprendendo bash esta semana e se deparou com um problema.
#!/bin/sh
if [ false ]; then
echo "True"
else
echo "False"
fi
Isso sempre produzirá True, mesmo que a condição pareça indicar o contrário. Se eu remover os suportes []
, ele funcionará, mas não entendo o porquê.
bash
conditional-operator
dez milhas
fonte
fonte
#!/bin/sh
não é um script bash - é um script sh POSIX. Mesmo que o interpretador POSIX sh no seu sistema seja fornecido pelo bash, ele desativa várias extensões. Se você deseja escrever scripts bash, use#!/bin/bash
ou seu equivalente localmente apropriado (#!/usr/bin/env bash
para usar o primeiro interpretador bash no PATH).[[ false ]]
também.Respostas:
Você está executando o comando
[
(akatest
) com o argumento "false", não executando o comandofalse
. Como "false" é uma sequência não vazia, otest
comando sempre é bem-sucedido. Para realmente executar o comando, solte o[
comando.fonte
bash
não possui um tipo de dados booleano e, portanto, nenhuma palavra-chave representando true e false. Aif
instrução apenas verifica se o comando que você fornece é bem-sucedido ou falha. Otest
comando pega uma expressão e obtém êxito se a expressão for verdadeira; uma seqüência de caracteres não vazia é uma expressão avaliada como verdadeira, assim como na maioria das outras linguagens de programação.false
é um comando que sempre falha. (Por analogia,true
é um comando que sempre tem sucesso.)if [[ false ]];
retorna verdadeiro também. Como fazif [[ 0 ]];
. Eif [[ /usr/bin/false ]];
também não pula o bloco. Como falso ou 0 pode ser avaliado como diferente de zero? Porra, isso é frustrante. Se isso importa, OS X 10.8; Bash 3.false
com uma constante booleana ou0
com um literal inteiro; ambos são apenas cordas comuns.[[ x ]]
é equivalente a[[ -n x ]]
qualquer stringx
que não comece com um hífen.bash
não tem quaisquer constantes booleanas em qualquer contexto. Seqüências de caracteres que se parecem com números inteiros são tratadas como tal por dentro(( ... ))
ou por operadores como-eq
ou por-lt
dentro[[ ... ]]
.if $predicate
podem ser facilmente abusadas para executar código hostil de uma maneira queif [[ $predicate ]]
não pode.Primer Booleano Rápido para Bash
A
if
declaração tem um comando como um argumento (como fazem&&
,||
, etc.). O código de resultado inteiro do comando é interpretado como um booleano (0 / null = true, 1 / else = false).A
test
instrução aceita operadores e operandos como argumentos e retorna um código de resultado no mesmo formato queif
. Um alias datest
declaração é[
, que é frequentemente usadoif
para realizar comparações mais complexas.As instruções
true
efalse
não fazem nada e retornam um código de resultado (0 e 1, respectivamente). Portanto, eles podem ser usados como literais booleanos no Bash. Mas se você colocar as instruções em um local em que elas sejam interpretadas como seqüências de caracteres, você terá problemas. No seu caso:Assim:
Isto é semelhante ao fazer algo como
echo '$foo'
vs.echo "$foo"
.Ao usar a
test
instrução, o resultado depende dos operadores utilizados.Em resumo , se você quiser apenas testar algo como aprovado / reprovado (também conhecido como "verdadeiro" / "falso"), passe um comando para sua declaração
if
ou&&
etc., sem colchetes. Para comparações complexas, use colchetes com os operadores adequados.E sim, eu estou ciente que não há tal coisa como um tipo boolean nativa em Bash, e que
if
e[
etrue
são tecnicamente "comandos" e não "declarações"; essa é apenas uma explicação funcional muito básica.fonte
if (( $x )); then echo "Hello"; fi
mostra a mensagem parax=1
mas não parax=0
oux=
(indefinida).Eu descobri que posso fazer alguma lógica básica executando algo como:
fonte
( $A && $B )
é uma operação surpreendentemente ineficiente - você gera um subprocesso por meio de chamada efork()
, em seguida, divide o conteúdo de$A
para gerar uma lista de elementos (neste caso, de tamanho um) e avalia cada elemento como um glob (neste caso, um que avalia por si próprio) e, em seguida, executa o resultado como um comando (nesse caso, um comando interno).true
efalse
strings vierem de algum outro lugar, existe o risco de elas realmente conterem conteúdo diferente detrue
oufalse
e você poderá obter um comportamento inesperado, incluindo a execução arbitrária de comandos.A=1; B=1
eif (( A && B ))
- tratá-los como numéricos - ou[[ $A && $B ]]
, que trata uma sequência vazia como falsa e uma sequência não vazia como verdadeira.Usar true / false remove algumas desordens de colchetes ...
fonte
[[ "$0" =~ "bash" ]]
o script funcione para mim.