As declarações de caso Bash são poderosas, mas fáceis de escrever. Ao revisitar um script antigo do Linux, você ficará feliz por ter usado uma case
declaração em vez de uma if-then-else
declaração longa .
Índice
A declaração do caso
A maioria das linguagens de programação tem sua versão de uma instrução switch
ou case
. Eles direcionam o fluxo de execução do programa de acordo com o valor de uma variável. Normalmente, há uma ramificação de execução definida para cada um dos valores possíveis esperados da variável e uma ramificação pega-tudo ou padrão para todos os outros valores.
A funcionalidade lógica é semelhante a uma longa sequência de if-then
instruções com uma else
instrução capturando tudo o que não foi tratado anteriormente por uma das if
instruções.
A implementação Bash de case
tenta combinar uma expressão com uma das cláusulas. Isso é feito examinando cada cláusula, por sua vez, tentando encontrar um padrão correspondente . Padrões em cláusulas são strings, mas – contra-intuitivamente – isso não significa que não podemos usar valores numéricos como a expressão.
O caso genérico
A forma genérica da case
declaração é esta:
expressão de caso em padrão-1) declaração ;; padrão-2) declaração ;; . . . padrão-N) declaração ;; *) declaração ;; esac
- Uma
case
declaração deve começar com acase
palavra – chave e terminar com aesac
palavra – chave. - A expressão é avaliada e comparada com os padrões em cada cláusula até que uma correspondência seja encontrada.
- A instrução ou instruções na cláusula correspondente são executadas.
- Um ponto e vírgula duplo “
;;
” é usado para encerrar uma cláusula. - Se houver correspondência de um padrão e as instruções dessa cláusula forem executadas, todos os outros padrões serão ignorados.
- Não há limite para o número de cláusulas.
- Um asterisco “
*
” indica o padrão padrão. Se uma expressão não corresponder a nenhum dos outros padrões dacase
instrução, a cláusula padrão será executada.
Um Exemplo Simples
Este script nos informa o horário de funcionamento de uma loja imaginária. Ele usa o date
comando com a +"%a"
string de formato para obter o nome do dia abreviado. Isso é armazenado na DayName
variável.
#! / bin / bash DayName = $ (data + "% a") echo "Horário de funcionamento de $ DayName" caso $ DayName em Seg) echo "09:00 - 17:30" ;; Ter) echo "09:00 - 17:30" ;; Casar) echo "09:00 - 12:30" ;; Qui) echo "09:00 - 17:30" ;; Sex) echo "09:00 - 16:00" ;; Sentado) echo "09:30 - 16:00" ;; Sol) echo "Fechado o dia todo" ;; *) ;; esac
Copie esse texto em um editor e salve-o como um arquivo chamado “open.sh.”
Precisamos usar o chmod
comando para torná-lo executável. Você precisará fazer isso para todos os scripts que criar ao trabalhar neste artigo.
chmod + x open.sh
Agora podemos executar nosso script.
./open.sh
O dia em que a captura de tela foi tirada é uma sexta-feira. Isso significa que a DayName
variável contém a string “Fri.” Isso corresponde ao padrão “Fri” da cláusula “Fri)”.
Observe que os padrões nas cláusulas não precisam ser colocados entre aspas duplas, mas não faz mal nenhum se estiverem. No entanto, você deve usar aspas duplas se o padrão contiver espaços.
A cláusula padrão foi deixada em branco. Qualquer coisa que não corresponda a uma das cláusulas anteriores é ignorada.
Esse script funciona e é fácil de ler, mas é prolixo e repetitivo. Podemos encurtar esse tipo de case
declaração com bastante facilidade.
Usando vários padrões em uma cláusula
Um recurso realmente interessante das case
instruções é que você pode usar vários padrões em cada cláusula. Se a expressão corresponder a qualquer um desses padrões, as instruções dessa cláusula serão executadas.
Aqui está um script que informa quantos dias há em um mês. Só pode haver três respostas: 30 dias, 31 dias ou 28 ou 29 dias para fevereiro. Então, embora sejam 12 meses, só precisamos de três cláusulas.
Neste script, o usuário é solicitado a inserir o nome de um mês. Para tornar o padrão de correspondência insensível a maiúsculas e minúsculas, usamos o shopt
comando com a -s nocasematch
opção. Não importa se a entrada contém maiúsculas, minúsculas ou uma mistura dos dois.
#! / bin / bash shopt -s nocasematch echo "Digite o nome de um mês" ler o mês caso $ mês em Fevereiro) echo "28/29 dias em $ mês" ;; Abril | Junho | Setembro | Novembro) echo "30 dias em $ mês" ;; Janeiro | Março | Maio | Julho | Agosto | Outubro | Dezembro) echo "31 dias em $ mês" ;; *) echo "Mês desconhecido: $ mês" ;; esac
Fevereiro tem uma cláusula para si mesmo e todos os outros meses compartilham duas cláusulas, dependendo de terem 30 ou 31 dias nelas. As cláusulas de padrões múltiplos usam o símbolo de barra vertical “|” como separador. O caso padrão captura meses mal escritos.
Salvamos isso em um arquivo chamado “month.sh” e o tornamos executável.
chmod + x mês.sh
Executaremos o script várias vezes e mostraremos que não importa se usamos letras maiúsculas ou minúsculas.
./month.sh
Como dissemos ao script para ignorar as diferenças em maiúsculas e minúsculas, qualquer nome de mês digitado corretamente é tratado por uma das três cláusulas principais. Meses mal escritos são capturados pela cláusula padrão.
Usando dígitos em declarações caseiras
Também podemos usar dígitos ou variáveis numéricas como a expressão. Este script pede ao usuário para inserir um número no intervalo 1..3. Para deixar claro que os padrões em cada cláusula são strings, eles foram colocados entre aspas duplas. Apesar disso, o script ainda corresponde à entrada do usuário para a cláusula apropriada.
#! / bin / bash echo "Digite 1, 2 ou 3:" ler número caso $ Number em "1") echo "Cláusula 1 correspondida" ;; "2") echo "Cláusula 2 correspondida" ;; "3") echo "Cláusula 3 correspondida" ;; *) echo "Cláusula padrão correspondida" ;; esac
Salve em um arquivo chamado “number.sh”, torne-o executável e execute-o:
./number.sh
Usando instruções case em for Loops
Uma case
instrução tenta corresponder ao padrão de uma única expressão. Se você tiver muitas expressões para processar, pode colocar a case
instrução dentro de um for
loop.
Este script executa o ls
comando para obter uma lista de arquivos. No for
loop, o arquivo globbing – semelhante, mas diferente das expressões regulares – é aplicado a cada arquivo para extrair a extensão do arquivo. Isso é armazenado na Extension
variável string.
A case
instrução usa a Extension
variável como a expressão que tenta corresponder a uma cláusula.
#! / bin / bash para arquivo em $ (ls) Faz # extrai a extensão do arquivo Extension = $ {File ## *.} caso "$ Extension" em sh) echo "Shell script: $ File" ;; md) echo "Arquivo Markdown: $ File" ;; png) echo "arquivo de imagem PNG: $ File" ;; *) echo "Desconhecido: $ File" ;; esac feito
Salve este texto em um arquivo chamado “filetype.sh”, torne-o executável e execute-o usando:
./filetype.sh
Nosso script de identificação de tipo de arquivo minimalista funciona.
Tratamento de códigos de saída com declarações de caso
Um programa bem comportado enviará um código de saída para o shell quando ele for encerrado. O esquema convencional usa um valor de código de saída de zero para indicar uma execução sem problemas e valores de um ou mais para indicar diferentes tipos de erro.
Muitos programas usam apenas zero e um. Agrupar todas as condições de erro em um único código de saída torna a identificação dos problemas mais difícil, mas é uma prática comum.
Criamos um pequeno programa chamado “go-geek” que retornava aleatoriamente códigos de saída zero ou um. Este próximo script chama go-geek
. Ele adquire o código de saída usando a $?
variável shell e usa-o como a expressão para a case
instrução.
Um script do mundo real faria o processamento apropriado de acordo com o sucesso ou falha do comando que gerou o código de saída.
#! / bin / bash go-geek case $? dentro "0") echo "A resposta foi: Sucesso" echo "Faça o processamento apropriado aqui" ;; "1") echo "A resposta foi: Erro" echo "Faça o tratamento de erros apropriado aqui" ;; *) echo "Resposta não reconhecida: $?" ;; esac
Salve isso em um script chamado “return-code.sh” e torne-o executável. Você precisará substituir o nosso go-geek
comando por algum outro comando. Você pode tentar cd
entrar em um diretório que não existe para obter um código de saída de um e, em seguida, editar seu script cd
para um diretório acessível para obter um código de saída zero.
A execução do script algumas vezes mostra os diferentes códigos de saída sendo identificados corretamente pela case
instrução.
./return-code.sh
Legibilidade ajuda na manutenção
Voltar aos antigos scripts Bash e descobrir como eles fazem o que fazem, especialmente se foram escritos por outra pessoa, é um desafio. Corrigir a funcionalidade de scripts antigos é ainda mais difícil.
A case
instrução fornece lógica de ramificação com sintaxe clara e fácil. É uma situação em que todos ganham.