Uso confuso de & & e || operadores

Eu estava folheando um arquivo /etc/rc.d/init.d/sendmail (sei que raramente é usado, mas estou estudando para um exame), e fiquei um pouco confuso sobre os operadores && e ||. Eu li onde eles podem ser usados em instruções como:

if [ test1 ] && [ test2 ]; then echo "both tests are true" elif [ test1 ] || [ test2 ]; then echo "one test is true" fi 

No entanto, este script mostra instruções de uma única linha, como:

[ -z "$SMQUEUE" ] && SMQUEUE="QUEUE" [ -f /usr/sbin/sendmail ] || exit 0 

Estes parecem estar usando os operadores && e || para obter respostas com base em testes, mas não fui capaz de desenterrar documentação a respeito desse uso específico desses operadores. Alguém pode explicar o que eles fazem neste contexto específico?

Resposta

O lado direito de && só será avaliado se o status de saída do lado esquerdo for zero (ou seja, verdadeiro). || é o oposto: avaliará o lado direito apenas se o status de saída do lado esquerdo for diferente de zero (ou seja, falso).

Você pode considerar [ ... ] para ser um programa com um valor de retorno. Se o teste interno for avaliado como verdadeiro, ele retornará zero; caso contrário, retorna diferente de zero.

Exemplos:

$ false && echo howdy! $ true && echo howdy! howdy! $ true || echo howdy! $ false || echo howdy! howdy! 

Observações extras:

Se você fizer which [, você verá que [ realmente aponta para um programa! No entanto, geralmente não é realmente aquele que é executado em scripts; execute type [ para ver o que realmente é executado. Se você quiser tentar usar o programa, basta fornecer o caminho completo, como então: /bin/[ 1 = 1.

Comentários

  • Quando você vê ” X ou Y “, você testa X. Se ‘ for verdadeiro, você já sabe a resposta para ” X ou Y ” (é ‘ é verdadeiro), então não há necessidade de testar Y. Se for ‘ verdade, você não ‘ não sabe a resposta para ” X ou Y “, então você precisa testar Y. Quando você vê ” X e Y ” , você testa X. Se ‘ for falso, você já sabe a resposta para ” X e Y ” (é ‘ s falso), s o não há necessidade de testar Y. Se X for verdadeiro, então você precisa testar Y para ver se ” X e Y ” é verdadeiro.
  • Em vez de ” se o lado esquerdo retornar zero “, eu escreveria ” se o comando do lado esquerdo ‘ o status de saída for zero “. Acho ” return ” um pouco ambíguo, pois a saída e o status de saída podem ser considerados como ” valores de retorno ”
  • Você não só pode ” considerar [ ... ] para ser um programa “, em muitos casos é . Ele ‘ está comumente no arquivo /bin/[ ou /usr/bin/[.
  • Programadores C acharão isso super confuso. Nesse caso, 0 significa falso … Enquanto no shellscripting 0 significa verdadeiro … Mente estourada.
  • @Calmarius Se você ‘ está acostumado com C, pense em return status, não booleanos, onde return 0 significa sucesso.

Resposta

Aqui está minha folha de dicas:

  • “A; B “Executar A e B, independentemente do sucesso de A
  • ” A & & B “Executar B se A for bem-sucedido
  • “A || B “Executar B se A falhar
  • ” A & “Executar A em segundo plano.

Comentários

  • Existem ‘ s alguns paralelos de cálculo lambda interessantes em andamento aqui demonstrados no JavaScript funcional (defina as variáveis em ordem); ” esquerdo (também conhecido como verdadeiro) “: (a => b => a). ” direito (também conhecido como falso) “: (a => b => b). ” A; B ” ” e ” (a => b => (() => b())(a())). ” A & & B ” ” se sem else (quando) ” (a => b => a()(() => right)(b)).” A || B ” ” else sem if (a menos) ” (a => b => a()(b)(() => right)). ” a & & b || c ” ” ifThenElse ” (a => b => c => (unless(when(a)(b))(c))()) .
  • observe que em bash, left é análogo 0 / string vazia, right análogo é todo o resto.
  • E uma única barra vertical?

Resposta

para expandir a resposta de @ Shawn-j-Goff “acima, && é um AND lógico e || é um OR lógico.

Veja esta parte do Guia de script de Bash avançado. Parte do conteúdo do link para referência do usuário, conforme abaixo.

& & E

if [ $condition1 ] && [ $condition2 ] # Same as: if [ $condition1 -a $condition2 ] # Returns true if both condition1 and condition2 hold true... if [[ $condition1 && $condition2 ]] # Also works. # Note that && operator not permitted inside brackets #+ of [ ... ] construct. 

|| OU

if [ $condition1 ] || [ $condition2 ] # Same as: if [ $condition1 -o $condition2 ] # Returns true if either condition1 or condition2 holds true... if [[ $condition1 || $condition2 ]] # Also works. # Note that || operator not permitted inside brackets #+ of a [ ... ] construct. 

Resposta

Pela minha experiência, uso o & & um d || para reduzir uma instrução if a uma única linha.

Digamos que estamos procurando um arquivo chamado /root/Sample.txt, então a iteração tradicional seria a seguinte no shell:

if [ -f /root/Sample.txt ] then echo "file found" else echo "file not found" fi 

Essas 6 linhas podem ser reduzidas a uma única linha:

[[ -f /root/Sample.txt ]] && echo "file found" || echo "file not found" 

Ao executar algumas iterações para definir variáveis ou para criar arquivos etc., a vida é mais fácil e o script parece mais elegante usando a função if de linha única, sua única desvantagem é que se torna um pouco mais difícil implementar vários comandos de uma única iteração, entretanto você pode fazer uso de funções.

Comentários

  • Isso é legal. Me lembra do código objc (a == b)? val = 1: val = 2;
  • Como posso usar este comando quando quero executar um processo em segundo plano com ” & “? Recebo um erro de sintaxe para ./someScript.sh & && echo 'ok' || echo 'ko'
  • No formato: foo && bar || baz, se foo for bem-sucedido, bar falhar, baz será executado, portanto, é sutilmente diferente de um if declaração.
  • Devo observar que é possível executar vários comandos em uma linha em {} parênteses, usando && ou ||, como: pidof udpxy > /dev/null 2>&1 && echo "udpxy is up!" || { echo "udpxy is down!"; /etc/init.d/udpxy restart; }. Também vale a pena mencionar que if..then..else é um ” reconhecedor ” mais confiável de verdadeiro / condições falsas do que usar && e ||.

Resposta

Existe uma noção de “atalho”.

Quando (expr1 && expr2) é avaliado – expr2 só é avaliado se exp1 for avaliado como” verdadeiro “. Isso ocorre porque expr1 E expr2 precisam ser verdadeiros para (expr1 && expr2) serem verdadeiros. Se expr1 for avaliado como “false” expr2 NÃO foi avaliado (atalho) porque (expr1 && expr2) já está “flase”.

Tente o seguinte – suponha que o arquivo F1 existe & arquivo F2 não existe:

( [ -s F1 ] && echo "File Exists" ) # will print "File Exists" - no short cut ( [ -s F2 ] && echo "File Exists" ) # will NOT print "File Exists" - short cut

Da mesma forma para || (ou) – mas curto o corte é invertido.

Comentários

  • A lógica geralmente é chamada de ” curto-circuito “. Eu ‘ nunca vi a frase ” atalho ” usada. Menciono isso para ajudar a encontrar referências.

Resposta

Os exemplos na resposta de Shawn J. Goff estão corretas, mas a explicação é inversa. Verifique:

O lado direito de & & só será avaliado se o status de saída do lado esquerdo for NONZERO. || é o oposto: ele avaliará o lado direito apenas se o status de saída do lado esquerdo for ZERO.

Comentários

  • Você está ciente de que para shells zero o código de saída é avaliado como verdadeiro e, portanto, o código de saída diferente de zero no lado esquerdo de && faz com que toda a expressão retorne falso ?
  • Alguém não aprovou suas edições porque não foi sua resposta.Se você acha que alguma resposta está incorreta, você deve votar negativamente e possivelmente deixar um comentário; se você acha que isso requer uma mudança, você deve deixar um comentário. A edição serve para corrigir erros de gramática, formatação e ortografia que não alteram o significado da resposta.
  • @countermode I ‘ desculpe, você está certo, Eu pensei que no Linux zero = falso e diferente de zero = verdadeiro (como em C e muitas outras linguagens / ambientes / plataformas). Peço desculpas pelo mal-entendido.

Deixe uma resposta

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