Introdução ao Shell Script – Baseado no livro de Ken O. Burtch

Introdução

Este artigo foi elaborado tendo como base, o livro Scripts de Shell Linux com Bash, do autor Ken O. Burtch, livro no qual eu estudei Shell Script e fiz um resumo pessoal. Deste resumo, resolvi redigir um texto ensinando como trabalhar com essa linguagem.

Esse artigo contém os seguintes tópicos:

  • Conceitos Iniciais,
  • Comando printf,
  • Códigos de Formatação,
  • Declaração de Variáveis,
  • Atributos de Variáveis,
  • Como Ler do Teclado,
  • Expressões aritméticas,
  • Comando if, Comando test,
  • Comparar Inteiro,
  • Laço for,
  • Funções de Shell,
  • Script Bem Comportado,
  • Declarações Globais,
  • Verificação de Sanidade,
  • Limpeza.

E, também, contém exercícios com respostas que eu elaborei para fixar melhor o conteúdo, já que o livro não traz exercícios. Com esse artigo, pretendo ajudar aqueles que desejam começar os estudos dessa linguagem e também, iniciando minhas contribuições com a comunidade.

Quando iniciei os estudos, percebi que havia muitas dúvidas referentes ao fato da linguagem Shell Script ser uma linguagem de programação ou, simplesmente, ser uma linguagem de comando.

Então, a primeira questão a ser pensada, é: o que caracteriza uma linguagem de programação?

Ela é caracterizada por ter estruturas condicionais, laços de repetição, a possibilidade de modularização, entre outras. Como a linguagem Shell Script tem essas características, ela pode ser considerada uma linguagem de programação.

Essa linguagem é utilizada para a construção de pequenas rotinas, como o seu próprio nome já diz, pois, apesar de não ter uma definição precisa do que seja Script, pode-se dizer que é um pequeno programa. É uma linguagem interpretada.

Para fins didáticos, é interessante o leitor ir testando os comandos à medida em que lê o texto, e os exercícios auxiliarão na fixação do conteúdo. Você pode testar os códigos direto do terminal, ou pode utilizar sites que tem o interpretador de shell.

Eu testei dois, que foram:

Os dois são muito bons. 

Conceitos iniciais

Para iniciar os estudos, é necessário conhecer alguns termos técnicos que serão utilizados no decorrer do artigo, e também, algumas informações essenciais para começar a criar os primeiros scripts:

  • Palavra chave :: é uma palavra, ou símbolo, que tem um significado especial para uma linguagem de computador. Ex.: case, do, for, function, while, [ ],{ }, etc.
  • Utilitários :: são comandos de propósito geral, úteis em muitas aplicações, como retornar a data ou contar o número de linhas de um arquivo. Ex.: date, wc.
  • Filtros :: são comandos que pegam os resultados de um comando e os modificam de alguma forma. Ex.: grep.
  • Argumentos :: são informações adicionais fornecidas para um comando, a fim de alterar seu comportamento. Ex.: date ‘+%H:%M’.
  • Chaves (opções ou flags). Ex.: ls –color, ls -l, ls -a. Obs.: as chaves e os argumentos são chamados coletivamente de parâmetros.
  • Para criar comentário, utiliza-se a tralha (#). Ex.: # Comentário.
  • A primeira linha de um arquivo de Shell Script, deve conter o caminho para o interpretador de shell. Ex.: #!bin/bash
  • O arquivo de Shell Script deve ser salvo com a extensão: .sh
  • Para rodar o arquivo de Shell Script, deve-se digitar no terminal: bash nomedoarquivo.sh
Comando printf / Variáveis

Comando printf

O comando interno printf, é utilizado para imprimir uma mensagem na tela. Abaixo, há alguns exemplos de sua utilização.

Para imprimir números inteiros, utiliza-se o comando abaixo:

$ printf “%d\n” 5

Obs.: o código %d, representa um número inteiro.

Pode-se inserir mais de um número em um mesmo comando, basta colocar dois códigos de formatação, conforme o exemplo abaixo:

$ printf “Há %d clientes com compras acima de %f.\n” 50 20000

Obs.: o código %f representa um número de ponto flutuante.

Para imprimir um número com sinal em uma coluna com largura de 10 caracteres, utilize o comando abaixo:

$ printf “%10d\n” 11

Códigos de formatação

Alguns exemplos de códigos de formatação que podem ser usados em conjunto com o comando printf:

  • %e :: exibe um número de ponto flutuante, mostrando em notação exponencial (também chamada de “científica”).
  • %f (ou %F) :: exibe um número de ponto flutuante sem exponencial.
  • %g (General) :: deixa o bash escolher %e ou %f, dependendo do valor.
  • %d (ou %i) :: representa um número com sinal.
  • %s :: exibe uma string.
  • \t :: tabulação.
  • \n :: iniciar uma nova linha.
  • \\ :: barra invertida.

Declaração de variáveis

A linguagem Shell Script é fracamente tipada, isso quer dizer que não necessita ser declarada. Quando não se declara uma variável, ela é tratada como String.

A tradição dita que as variáveis sejam escritas em maiúsculo, pois a maior parte dos comandos são em minúsculo. Abaixo, estão alguns exemplos sobre como utilizar as variáveis.

Para atribuir uma String vazia, basta utilizar a variável da seguinte maneira:

CUSTO=

Para ver o que está contido dentro da variável, utiliza-se o símbolo do cifrão antes da variável, como mostra o exemplo abaixo:

$ printf “%s” $CUSTO

As aspas no Shell Script não são utilizadas para identificar um valor, como String, mas sim, para delimitar onde começa e termina o valor.

Teste os comandos abaixo compreender melhor:

$ CUSTO=Maria Joao Carlos

Se você tentar executar esse comando, você perceberá que ocorrerá um erro, pois o bash não consegue identificar que a palavra Joao e Carlos fazem parte da mesma estrutura.

Para que ele possa identificar Maria Joao Carlos como um único valor a ser recebido pela variável, você terá que delimitar utilizando aspas duplas, conforme o exemplo abaixo:

$ CUSTO=”Maria João Carlos”
$ printf “%s” $CUSTO

Se você deseja colocar um valor contido em uma outra variável concatenando com outros valores, poderá fazer de duas formas:

1. A primeira, é delimitando a variável dentro das aspas duplas. Para entender melhor, teste o comando baixo.

$ TAXA=7,25
$ MENSAGEM_DA_TAXA=”A taxa é “”$TAXA””%”
$ printf “%s” “$MENSAGEM_DA_TAXA”

2. A segunda forma, é delimitando a variável dentro de chaves, conforme o exemplo abaixo:

$ MENSAGEM_DA_TAXA=”A taxa é ${TAXA} %”
$ printf “%s” “$MENSAGEM_DA_TAXA”

Uma observação importante, é que, se você utilizar aspas simples, o bash não reconhecerá como uma variável e sim como uma String. Teste o comando abaixo e verificará que será impresso na tela:$MENSAGEM_DA_TAXA

$ printf “%s” ‘$MENSAGEM_DA_TAXA’

Dica: o bash costuma dar erro de espaçamentos, então, sempre deixe sem espaço entre o sinal de igual, a variável e o valor. Exemplo:

Modo errado:

MENSAGEM_DA_TAXA = “A taxa é ${TAXA} %”

Modo correto:

MENSAGEM_DA_TAXA=”A taxa é ${TAXA} %”

Atributos de variáveis

Todas as variáveis bash são armazenadas como Strings simples. Cada variável tem determinadas opções chamadas atributos, que podem ser ligadas, ou desligadas, usando o comando declare.

Para declarar uma variável do tipo inteiro, basta utilizar a opção -i no comando declare. Exemplo:

$ declare -i NUMERO_CONTAS=15
$ printf “%d” “NUMERO_CONTAS”

Para declarar uma constante utilizando o atributo -r do comando declare, assim o valor contido na variável não será modificado no decorrer do programa.

$ declare -r COMPANHIA=”Smith and Jones”
$ printf “%s\n” “COMPANHIA”

Pode utilizar o atributo -p no comando declare para visualizar o que está contido na variável.

$ declare -p NUMERO_CONTAS

Para destruir a variável, utilize o comando unset, antes da variável:

$ unset CUSTO

Como ler do teclado / Expressões aritméticas

Como ler do teclado

Para ler do teclado, é utilizado o comando read. O comando interno read pára o script e espera que o usuário digite algo no teclado.

O texto digitado é atribuído à variável que acompanha o comando read. Abaixo, há alguns exemplos com a sua devida explicação, para que você possa testar, e assim, aprender como utilizar esse comando.

Essa é uma utilização clássica do read, onde simplesmente ele pára e espera o usuário digitar algum valor. Assim que o valor é inserido, pode-se visualizar o que foi inserido na variável através do comando printf:

$ printf “Arquivos guardados por quantos dias?”
$ read DIAS_DE_ARMAZENAMENTO
$ printf “%s” “$DIAS_DE_ARMAZENAMENTO”

Neste exemplo, é utilizado a opção -p do read, fazendo que ele tenha duas funções a de exibir na tela uma mensagem e guardar na variável o que o usuário digitar.

$ read -p “Arquivos guardados por quantos dias?” DIAS_DE_ARMAZENAMENTO
$ printf “%s” “$DIAS_DE_ARMAZENAMENTO”

Neste exemplo, ele utiliza a opção -t, com o valor 5, sendo assim, o usuário terá cinco segundos para digitar o valor, se caso não for digitado nada, o programa continuará normalmente.

$ read -t 5 NOME_DO_ARQUIVO
$ printf “%s” “$NOME_DO_ARQUIVO”

Com a opção -n, será criado um limite de caracteres para ser digitado.

$ read -n 10 NOME_DO_ARQUIVO
$ printf “%s” “$NOME_DO_ARQUIVO”

Expressões aritméticas

O comando let executa cálculos matemáticos. let espera uma String contendo uma variável, um sinal de igual e uma expressão a ser calculada. O resultado é atribuído a uma variável. Abaixo, há alguns exemplos de sua utilização.

Nesse exemplo, a variável recebe a soma de dois números:

$ let “SOMA=5+5”
$ printf “%d” “SOMA”

Nesse exemplo, a variável recebe o valor contido nela mais cinco:

$ let “SOMA=$SOMA+5”
$ printf “%d” “%SOMA”

Obs.: se uma variável for declarada como um número inteiro com a opção -i, o comando let será opcional.

Exemplos com as operações de: soma, subtração, multiplicação, divisão e resto da divisão:

$ let “RESULTADO=5+2″
$ printf ” 5 mais dois é %d\n” “$RESULTADO”

$ let “RESULTADO=5-2″
$ printf ” 5 menos dois é %d\n” “$RESULTADO”

$ let “RESULTADO=5*2″
$ printf ” 5 vezes dois é %d\n” “$RESULTADO”

$ let “RESULTADO=5/2″
$ printf ” 5 dividido dois é %d\n” “$RESULTADO”

$ let “RESULTADO=5%2″
$ printf ” o resto de 5 dividido por 2 é é %d\n” “$RESULTADO”

Obs.: apenas expressões inteiras são permitidas.

Comando if e test / Laço for

Comando if

O comando interno if, executa o comando e verifica os resultados. Se o comando teve sucesso, ele executa outro conjunto de comandos. O único comando normalmente usado com if test.

Estrutura básica:

if [ parâmetros ]; then
declarações a executar
elif [ parâmetros ]; then
declarações a executar
else
declarações a executar
fi

Obs.: o comando test, foi substituído pelo colchete.

Comparar par de Strings:

  • s1 == s2 → verdadeiro se a string s1 for igual a s2
  • s1 != s2 → verdadeiro se a string s1 não for igual a s2
  • s1 < s2 → verdadeiro se a string s1 for menor que a s2
  • s1 > s2 → verdadeiro se a string s1 for maior que s2

Comparar inteiro

Apesar do livro não falar sobre comparação de inteiros, achei interessante colocar aqui.

  • -lt → (less than), menor que, equivalente ao <.
  • -gt → (greather than), maior que, equivalente ao >.
  • -le → (less or equal), menor ou igual, equivalente ao <=.
  • -ge → (greater or equal), maior ou igual, equivalente ao >=.
  • -eq → (equal), igual, equivale ao =.
  • -ne → (not equal) diferente. Equivale ao != que usamos a pouco.

Comando test

Para representar a condição and é && para representar “ou” é || e a negação é representado pela exclamação !.

Exemplo:

#!/bin/bash
A=5
B=15
if [ $A == 5 ] && [ $B == 15 ]; then
echo “Verdadeiro”
else
echo “Falso”
fi

Laço for

O laço for, como encontrado em outras linguagens de programação, é criado usando um let aninhado (assim como o test utiliza colchetes, pode-se representar o let com dois parênteses. Exemplo: ((Variáveis)))

Exemplo:

#!/bin/bash
#Conta de 1 até 9

for((CONTATODOR=1 ; CONTADOR<10 ; CONTADOR++)) ; do
printf “\n O contador vale agora %d \t” “$CONTADOR”
done
exit 0

Funções de shell

As funções são uma forma de inserir pequenos subscripts em um script. Como scripts separados, as funções podem ser usadas para dividir um script complexo em tarefas separadas e com nome, para que, com isso, melhorar a legibilidade.

Pontos importantes:

  • Da mesma forma que variáveis, as funções devem ser declaradas antes que possam ser usadas.
  • Em vez de declare, as funções são declaradas usando o comando function.
  • Cada função tem um nome, e as declarações que a compõem, ficam dentro de chaves.

Exemplo 01:

#!/bin/bash

function BoasVindas(){
printf “\n\n Seja Bem Vindo $1 \n\n”
}

printf “\n Digite seu nome: \t”
read NOME
BoasVindas “$NOME”

No exemplo 01, a variável enviada para a função é identificada como $1, se fossem duas variáveis a ser enviadas, teria o $2, e assim por diante

Exemplo 02:

#!/bin/bash

function mostraMensagem() {
declare -g a b
a=”$1″
b=’Hello World!’
}

mostraMensagem ‘Olá Mundo!’
printf “\n %s” “$b”

Nesse segundo exemplo, declarou duas como globais. Teste o programa para entender melhor o que ocorre.

Script bem comportado

Um script bash bem estruturado, tem que conter os cinco itens abaixo:

  • Cabeçalho
  • Declarações globais
  • Verificação de sanidade
  • Script principal
  • Limpeza

Cabeçalho :: O cabeçalho define que tipo de script, quem o escreveu, qual a sua versão e quais suposições, ou opções, de shell bash ele faz. A primeira linha é o cabeçalho, começa com #!, assim identifica o tipo de script. O GNU/Linux usa essa informação para iniciar o programa certo para executar o script.

Normalmente é esse: #!bin/bash

Exemplo:

#!/bin/bash
#Esvaziar os discos se ninguém estiver no computador
#Calebe B. Oliveira
#Versão

Declarações globais :: Todas as declarações que aplicam a todo o script, devem ser feitas no topo dele.

Exemplo:

declare -rx who=”/usr/bin/who”
declare -rx sync=”/bin/sync”
declare -rx wc=”/usr/bin/wc”

Verificação de sanidade :: Antes que um script execute alguma declaração, é preciso verificar que todos os arquivos necessários estejam acessíveis. Todos os comandos requisitados devem ser executáveis e armazenados nas localizações esperadas.

Estas verificações são, às vezes, chamadas de verificação de sanidade, porque não deixam o script começar sua tarefa principal, a não ser que o computador esteja em um estado conhecido, ou “são”.

Exemplo:

if test ! -x “$who” ; then
printf “O comando who não está disponível abortando \ n”
exit 192
fi

Script principal :: Quando você tiver verificado que o sistema está são, o script poderá continuar a executar seu trabalho.

Exemplo:

declare -i N
function ExibeNaTela(){
for(( CONT=0 ; CONT<$1 ; CONT++ )) ; do
printf “\n %s” “$2”
done
}
printf “\n Digite um valor para ser exibido \t”
read S
printf “\n Digite a quantidade de vezes que a mensagem deverá ser exibida \t”
read N
ExibeNaTela “$N” “$S”

Limpeza :: Quaisquer arquivos temporários devem ser apagados, e o script retorna um código de estado para a pessoa, ou programador, que o esteja executando.

Exemplo:

exit 0
Exercícios

Exercício 01

Faça um programa que receba a idade de duas pessoas e verifique qual das duas é maior e imprima na tela a idade da pessoa mais velha.

Resposta:

#!/bin/bash
declare -i IDADE1
declare -i IDADE2

printf “\n Digite a idade da primeira pessoa”
read IDADE1
printf “\n Digite a idade da segunda pessoa”
read IDADE2
printf “$IDADE1 $IDADE2”
if [ “$IDADE1” -gt “$IDADE2” ] ; then
printf “\n A maior idade e %d” “$IDADE1”
else
printf “\n A maior idade e %d” “$IDADE2”
fi
exit

Exercício 02

Escreva um algoritmo para ler um valor inteiro e escrever se ele está entre os números 1 e 10, ou não está.

Resposta:

#!/bin/bash
declare -i NUMERO
printf “\n Digite um número para verificar se ele está entre 1 e 10”
read NUMERO
if [ $NUMERO -ge 1 ] && [ $NUMERO -le 10 ] ;  then
printf “\n O número está entre 1 e 10”
else
printf “\n O número não está entre 1 e 10”
fi

exit

Exercício 03

Faça um algoritmo para ler: a descrição do produto (nome), a quantidade adquirida e o preço unitário. Calcular e escrever o total (total = quantidade adquirida * preço unitário), e o total a pagar (total a pagar = total – desconto), sabendo-se que:

  • Se quantidade <= 5 o desconto será de R$ 2.
  • Se quantidade > 5 e quantidade <=10 o desconto será de R$ 3.
  • Se quantidade > 10 o desconto será de R$ 5.

Resposta:

#!/bin/bash
declare -i QTDAD
declare -i PRECOUNI
declare -i TOTAL
declare -i DESCONTO
printf “\n Digite a descrição do produto \t”
read NOME
printf “\n Digite a quantidade adquirida \t”
read QTDAD
printf “\n Digite o preço unitário do produto \t”
read PRECOUNI
TOTAL=”$QTDAD * $PRECOUNI”
if [ “$QTDAD” -le 5 ] ; then
DESCONTO=”$TOTAL – 2 ”
elif [ “$QTDAD” -gt 5 ] && [ “$QTDAD” -le 10 ] ; then
DESCONTO=”$TOTAL – 3″
else
DESCONTO=”$TOTAL – 5″
fi
printf “\n Para o produto %s \t” “$NOME”
printf “\n O valor total do produto adquirido é \t %d” “$TOTAL”
printf “\n O valor com desconto é %d \t” “$DESCONTO”
exit

Exercício 04

Elabore um programa que solicite ao usuário o sexo e a altura de 10 pessoas. Calcular e escrever o peso ideal de acordo com a fórmula a seguir:

  • Homens: (72 * h ) – 58
  • Mulheres: (62 * h ) – 44

Resposta:

#!/bin/bash
declare -i ALTURA
declare -i CALCULO
for (( CONT=0 ; CONT<10 ; CONT++ )) ; do
printf “\n Digite M para masculino e F para feminino \t”
read SEXO
printf “\n Digite a sua altura \t”
read ALTURA
if [ “$SEXO” == F ] ; then
CALCULO=”62 * $ALTURA – 44″
elif [ “$SEXO” == M ] ; then
CALCULO=”72 * $ALTURA – 58″
else
printf “Opção inválida”
fi
printf “\n Para o sexo %s o peso ideal é %d \t” “$SEXO $CALCULO”
done

Exercício 05

Faça um programa que leia um número inteiro (limite), um incremento (incr, inteiro) e imprima os números inteiros de 0 até limite, com incremento de incr. Suponha que limite e incr são maiores que zero.

Exemplo:

  • Valores lidos: 10 (limite) 3 (incr)
  • Saída do programa: 0 3 6 9

Resposta:

#!/bin/bash
declare -i LIMITE
declare -i INCR
printf “\n Digite o limite \t”
read LIMITE
printf “\n Digite o incremento \t”
read INCR
for (( CONT=0; CONT<$LIMITE; CONT=$CONT+$INCR)) ; do
printf “\t %d \t” “$CONT”
done
exit

Exercício 06

Crie um script que realize a leitura dos dados, de uma String S e um valor inteiro N, e crie uma função que exiba na tela o valor da variável S por N vezes seguidas.

Resposta:

#!/bin/bash

declare -i N
function ExibeNaTela(){
for(( CONT=0 ; CONT<$1 ; CONT++ )) ; do
printf “\n %s” “$2”
done
}
printf “\n Digite um valor para ser exibido \t”
read S
printf “\n Digite a quantidade de vezes que a mensagem deverá ser exibida \t”
read N
ExibeNaTela “$N” “$S”

Exercício 07

Crie uma função que receba dois números inteiros positivos X e Y, e retorne a soma dos N números existentes entre eles (inclusive X e Y). Exiba a soma.

Resposta:

#!/bin/bash

declare -i X Y
function SomaPositivo(){
declare -g SOMA
REC=”$1″
REC2=”$2″
SOMA=”0″
for(( CONT=$REC ; CONT<$REC2 ; CONT++ )) ; do
let “SOMA=$SOMA+$CONT”
done
}
printf “\n Digite um número \t”
read X
printf “\n Digite um número \t”
read Y
SomaPositivo “$X” “$Y”
printf “\n O valor de x é %d o valor de y é %d” “$X” “$Y”
printf “\n A soma dos valores é %s” “$SOMA”
exit

ReferênciaScripts de Shell Linux com Bash (Ken O. Burtch)

Rolar para cima