Estou tentando criar um if else
script bash que usa três variáveis booleanas:
CHECK_X
CHECK_Y
CHECK_Z
Se CHECK_X
ou CHECK_Y
for falso e CHECK_Z
também for falso , informo ao usuário que as condições não foram atendidas. Então criei o seguinte:
if [[ "$CHECKX" || "$CHECKY" == "FALSE" ]] && [[ "$CHECKZ" == "FALSE" ]]; then
echo "Condition not met"
fi
Usando o código acima, se CHECK_X
ou CHECK_Y
estiver correto, apesar de CHECK_Z
ainda ser falso , a condição continua, o que não é o que eu quero.
Preciso CHECK_X
que e CHECK_Z
seja verdadeiro ou CHECK_Y
e CHECK_Z
seja verdadeiro antes que minha condição seja atendida.
Usar o código a seguir também não funcionou:
if [[ "$CHECK_X" && "$CHECK_Z" == "FALSE" ]] || [[ "$CHECK_Y" && "$DCHECK_Z" == "FALSE" ]]; then
echo "Condition not met"
fi
Acho que me compliquei demais em algum lugar e esperava conselhos de especialistas. Obrigado
ATUALIZAR:
A partir de alguns comentários recentes, atualizei meu código para:
if [[ "$CHECK_X" == "FALSE" || "$CHECK_Y" == "FALSE" ]] && [[ "$CHECK_Z" == "FALSE" ]]; then
echo "Condition not met"
fi
No entanto, após o teste, tenho o seguinte ...
se:
CHECK_X="TRUE"
CHECK_Y="FALSE"
CHECK_Z="TRUE"
Saída: Condition not met
. Isso está incorreto porque as condições 1 e 3 são TRUE
.
se:
CHECK_X="TRUE"
CHECK_Y="FALSE"
CHECK_Z="FALSE"
Saída: Condition not met
. Isso está correto porque as condições 1 e 3 não são TRUE
.
se:
CHECK_X="FALSE"
CHECK_Y="TRUE"
CHECK_Z="FALSE"
Saída: O script é concluído. Isto está incorreto porque as condições 2 e 3 não são TRUE
.
se:
CHECK_X="FALSE"
CHECK_Y="TRUE"
CHECK_Z="TRUE"
Saída: O script é concluído. Isso está correto porque as condições 2 e 3 são TRUE
.
se:
CHECK_X="FALSE"
CHECK_Y="FALSE"
CHECK_Z="FALSE"
Saída: Condition not met
. Isto está correto porque as condições 1 e 3 ou 2 e 3 não são TRUE
.
Você precisa verificar cada variável:
Quando você tinha
if [[ "$CHECKX" || "$CHECKY" == "FALSE" ]]
, isso é apenas verificar se$CHECKX
está definido, ele apenas compara$CHECKY
com a stringFALSE
. Ilustrar:Como você pode ver acima, a verificação só falhou quando
CHECKX
foi definida como a string emtpy, então o teste[[ "$CHECKX" ]]
foi avaliado como falso. Se for definido como qualquer coisa, incluindo0
, então falhará:Outros abordaram suas técnicas de codificação para armazenar e testar valores e variáveis booleanas, então vou me concentrar apenas na lógica do seu código.
Quando você estiver trabalhando para entender uma função booleana multivariável, crie uma tabela verdade para ter certeza de qual deve ser a saída correta de sua função. Verifique se entendi sua postagem corretamente, mas acredito que para uma função
Q(X,Y,Z)
o valor deQ
depende deX
,Y
eZ
da seguinte forma:"Se X ou Y for falso e Z também for falso, então... as condições não serão atendidas."
Como você declarou isso de forma negativa, presumirei que, em todos os outros casos, a condição é atendida.
Um axioma comum na álgebra booleana é que em vez de construir uma função Q que resolva todos os casos, podemos construir duas subfunções Q1 e Q2 que resolvam partes exclusivas da tabela. Então podemos simplesmente usar
OR
os resultados de Q1 e Q2 para obter a solução final Q.Por exemplo, seja Q1 a solução onde
X
é FALSO, na metade superior da tabela. Observe que nesses quatro casos, as colunasZ
eQ
são idênticas. AY
coluna é irrelevante, então podemos dizer que quandoX
for FALSE, o resultado da função está diretamente relacionado aZ
:Na metade inferior da tabela, onde
X
é TRUE, o resultado da função Q2 está diretamente relacionado aY || Z
:Como Q1 e Q2 são definidos em domínios totalmente separados, podemos afirmar que o resultado Q será precisamente um ou outro. Aquilo é,
Agora precisamos combinar estes dois casos numa única fórmula booleana. É tentador simplesmente concatenar tudo, mas para uma fórmula booleana correta, temos que considerar a ordem de avaliação. Semelhante à álgebra normal, onde a multiplicação é realizada antes da adição, a álgebra booleana determina que a interseção (AND) seja realizada antes da união (OR). Portanto, colocaremos parênteses em torno das subexpressões.
Ou
X
é falso e nosso resultado éZ
:Ou
X
é verdade e nosso resultado éY || Z
:E nossa resposta é literalmente uma OU outra:
A avaliação de curto-circuito e a comutação da união nos permitiriam reafirmar isso como:
Substituting for Q1 and Q2:
With parentheses only where needed:
which can also be written:
When Z is true, the right side of the OR is irrelevant. When Z is false, the right side of the OR becomes:
or just:
so our final function Q is:
We can verify this against the truth table, because in every case where Z is true, Q is also true. In the four cases where Z is false, Q is true only when X and Y are both true.
Expressar seus requisitos em [múltiplos] negativos duplos ("Se CHECK_X ou CHECK_Y for falso e CHECK_Z também for falso , então informo ao usuário que as condições não foram atendidas.") torna muito mais difícil entendê-los e implementá-los do que se você expressasse eles de uma forma positiva.
Evite usar negativos como
!
ounot
comparações com qualquer variação emfalse
seus requisitos ou código e evite usar qualquer termo negativo comonot
em nomes de variáveis pelo mesmo motivo - positivos são sempre mais fáceis de entender do que negativos e se você não tiver negativos então você não posso acabar com duplas negativas extremamente difíceis de entender.Aqui está o que você disse que é sua exigência:
e podemos traduzir diretamente seus requisitos em pseudocódigo como:
Agora, para tornar tudo menos negativo, se primeiro virarmos para que as
if
"condições sejam atendidas" (ou seja, positivas em vez de negativas) sejam a condição que está sendo testada, então ela se tornará:Portanto, agora temos um
if
teste que nos leva a um estado positivo de "condições foram atendidas", em vez de negativo, de "condições não atendidas ". Agora só precisamos tornar oif
teste em si positivo, em vez de negativo, fatorando o operador "não" inicial,!
e alterando as comparações comfalse
para comparações comtrue
.Se aplicarmos a álgebra booleana para mover a negação
!
dentro dos parênteses mais externos, a condição se tornará:e se aplicarmos o mesmo novamente para mover o primeiro
!
dentro da condição a que se aplica, obteremos:que podemos simplificar alterando cada um
!...false
paratrue
:e agora temos um
if
teste totalmente positivo produzindo um resultado positivo "as condições foram atendidas" e de repente fica muito claro que sua exigência é simplesmente que se CHECK_Z ou ambos CHECK_X e CHECK_Y forem verdadeiros, então a condição foi atendida, caso contrário, é ' t e assim podemos implementar facilmente esse requisito usando umif-else
como acima ou de forma mais sucinta como:I would focus on the readability of the logic flow in the code, so instead of writing a single complicated structure that does all the work, that later when you forgot about and need to understand you have to go through mental gymnastics, make the code into simple steps that are easy to follow.
For example, if I understand you correctly, if
CHECK_Z
isTRUE
then you don't need to check onCHECK_X
orCHECK_Y
. So only ifCHECK_Z
isFALSE
you have to check the others. I added a variableconditions_met
, that you will use when you need to follow the program and print messages, for example.I simplified the variable names for clarity, and assumed each one can have a boolean value, either 'TRUE' or 'FALSE' (in bash I'd use 0 and 1 maybe, not a string).
If you want Booleans in BASH, than the closest to a real Boolean is using a
Number and the Shell Arithmetic.
Because:
CHECK_X="true"; [[ $CHECK_X == "true" ]];
is a string comparison, where the right parameter is a glob pattern, if not quoted, and which then generates something like a boolean, exit code 0 or 1
tente aritmética do shell:
Honestamente, com todas as informações que você postou, é muito difícil escolher como você deseja que isso funcione.
Estou baseando minha solução abaixo em sua declaração da seguinte forma:
Conforme discutido de outra forma, encadear condições negativas é um trabalho árduo. Para esse tipo de lógica, talvez seja melhor usar indevidamente a
case
dentro de uma função - e, em vez disso, verificar os pontos positivos.Aqui está em ação
Experimente on-line!
my take on it: