Trilhas
/
Bash
Bash
/
Programa
/
Condicionais
Co

Condicionais em Bash

{one: "1 exercício", many: "%{count} de exercícios", other: "%{count} exercícios"}

Sobre Condicionais

Veracidade no Bash

O Bash não tem o conceito de valores Boolean. Existem strings e números, e arrays de strings ou números. Então, como os comandos condicionais lidam com verdadeiro e falso?

Status de saída

Os comandos produzem um status de saída quando terminam. Um status de saída é um número inteiro entre 0 e 255, inclusive. O Bash considera que um status de saída zero representa sucesso. Qualquer outro status de saída representa falha.

Isso vale para todos os comandos, incluindo comandos internos do Bash, palavras-chave e funções.

O comando "if"

A sintaxe básica do comando if é

if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi

Ele começa com if; os comandos de condição são separados dos comandos de "sucesso" por then; e termina com fi. A cláusula else é opcional.

CONDITIONAL_COMMANDS pode ser um único comando ou uma lista de comandos.

Os CONDITIONAL_COMMANDS são executados e

  • se o status de saída for zero (sucesso), os TRUE_COMMANDS são executados.
  • se o status de saída for diferente de zero (falha), os FALSE_COMMANDS são executados, se estiverem presentes.

É possível criar bifurcações em cascata com elif

if CONDITIONAL_COMMANDS
then TRUE_COMMANDS
elif CONDITIONAL_COMMANDS_2
then TRUE_COMMANDS_2
# more elif branches ...
else FALSE_COMMANDS
fi

É preciso haver um ponto e vírgula ou uma quebra de linha antes das palavras then, elif, else e fi.

Vale reforçar: é o status de saída dos comandos condicionais que controla o fluxo. Por exemplo, o grep retorna 0 se encontrar uma correspondência e 1 se não encontrar. A opção -q suprime a saída, produzindo apenas o status de saída.

if grep -q "my pattern" my_file; then echo "the pattern is found in the file"; fi

Os comandos "[" e "test"

Não há nenhuma sintaxe especial em torno dos CONDITIONAL_COMMANDS. Talvez você já tenha visto condicionais assim:

if [ "$password" = "secure" ]; then
    echo "Welcome!"
fi

O [ não é sintaxe especial. É um comando que avalia a expressão condicional e termina com um status de sucesso ou falha. Como todos os comandos, é obrigatório haver espaço em branco entre ele e seus argumentos.

Na verdade, o [ é um sinônimo do comando test. Eles são exatamente iguais, exceto que o último argumento de [ precisa ser ].

Expressões condicionais

Dentro de [ e ], você escreve uma expressão condicional. Algumas expressões condicionais típicas incluem:

[ -f "$filename" ]             # file operations
[ "$string1" = "$string2" ]    # string comparisons
[ "$num1" -eq "$num2" ]        # arithmetic comparisons

Há muitas outras operações disponíveis; elas estão listadas na seção Expressões condicionais do Bash do manual.

Note

Nos exemplos acima, repare que todas as variáveis estão entre aspas. Os comandos test e [ são comandos comuns, nos quais os argumentos estão sujeitos à divisão de palavras e à expansão de nomes de arquivos como qualquer outro comando.

Vale destacar isso porque as expressões condicionais são avaliadas de formas diferentes dependendo de quantos argumentos você fornece:

  • 0 argumentos: o status de saída é diferente de zero (falha)
  • 1 argumento: o status de saída é zero (sucesso) se o argumento não estiver vazio, e diferente de zero se estiver vazio.
  • 2 argumentos: o primeiro argumento precisa ser um operador unário (como em [ -z "$name" ]) ou um ! (que nega o status do teste de 1 argumento)
  • e mais.

Você pode obter resultados inesperados se esquecer de usar aspas:

str=""

# this prints "empty"
if [ -n "$str" ]; then echo "not empty"; else echo "empty"; fi

# leaving the variable unquoted results in incorrect "not empty" output
if [ -n $str ]; then echo "not empty"; else echo "empty"; fi

A palavra-chave "[["

A construção condicional [[...]] não é um comando, é uma palavra-chave. Isso significa que, embora seja tratada como qualquer outro comando, ela tem regras de análise sintática especiais. O que há de especial no [[ é que as variáveis expandidas dentro dele não estão sujeitas à divisão de palavras nem à expansão de nomes de arquivos. Isso significa que esse comando se comporta como você espera, mesmo sem aspas.

if [[ -n $str ]]; then echo "not empty"; else echo "empty"; fi

O [[ suporta todas as expressões condicionais que o test e o [ conseguem lidar. Além disso, o [[ oferece

  • o operador =~ de correspondência de expressões regulares;
  • == e != que funcionam como operador de correspondência de padrões glob;
  • && e || como operadores lógicos (regra de análise sintática especial);
  • < e > como operadores de comparação de strings "puros" (regra de análise sintática especial: como esses são símbolos de redirecionamento, no [ eles precisam ser escapados).

Há uma opinião amplamente difundida de que esses recursos especiais oferecem tantos benefícios que o [[ deveria ser usado exclusivamente. (Por exemplo, o Google Shell Style Guide.)

O comando "case"

O case é outro comando de fluxo de controle. Ele é como uma instrução "switch" em outras linguagens.

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac

A WORD é comparada com cada PATTERN. Quando uma corresponde, os COMMANDS são executados.

read -p "Guess the secret word: " word
case "$word" in
    secret) echo "Yes, you guessed it!" ;;
    ??????) echo "That's the right number of letters." ;;
    s*)     echo "You guessed the first letter." ;;
    *)      echo "Not even close! Try again." ;;
esac

Cada cláusula COMMANDS precisa terminar com dois pontos e vírgulas, ;;.

Note
  1. Existem alternativas que oferecem funcionalidade para a execução de comandos em cascata e para a correspondência de padrões continuar. Consulte o manual para mais detalhes.
  2. Lembre-se de que falamos sobre padrões na seção Expansão de nomes de arquivos do conceito Quoting.
Editar via GitHub O link abre em uma nova janela ou aba