Programação
 
 
Shell
(Programação Shell)



IF (tomada de decisão)
exemplo1:
if [ -x /sbin/ifconfig ] (pergundo se o "/sbin/ifconfig" é um executável)
then (então)
echo É um executável.
else (senão)
echo Não é um executável.
fi (fim desse "if")
Obs: a tomada de decisão acima é equivalente a "if [ -x /sbin/ifconfig ]; then echo É um executável.; else echo Não é um executável.; fi" . Para ob ter ajuda digite "help if".



WHILE (condição - executa um loop até que condição seja falsa)
exemplo1:
verify=n ()
while [ $verify = n ] ()
do ()
echo "Opção de Entrada: "
read option
echo "Você entrou com $option. Está correto? (y/n)"
read verify
done ()
Obs: a condição acima é equivalente a "verify=n ; while [ $verify = n ]; do echo "Opção de Entrada: "; read option; echo "Você entrou com $option. Está correto? (y/n)" ; read verify; done" . Para obter ajuda digite "help while".



UNTIL (condição - executa um loop até que condição seja verdadeira)
exemplo1:
n=1 ()
until [ "$n" -ge 66 ] ()
do ()
echo Digite o valor de n:
read n
done ()
Obs: a condição acima é equivalente a "n=1 ; until [ "$n" -ge 66 ]; do echo Digite o valor de n: ; read n; done" . Para obter ajuda digite "help until".



FOR ou SELECT (loop)
exemplo1:
for i in 1 2 3 4 5 (inicia um loop num sequência de 1 à 5)
do (faça)
echo $i >> teste (devia a saída padrão do valor de "i" a cada loop para o arquivo "teste")
done (feito)
Obs: o loop acima é equivalente a "for i in 1 2 3 4 5; do echo $1 >> teste; done" .
exemplo2:
for n in $(seq 1 5) (inicia um loop num sequência de 1 à 5)
do (faça)
echo $n >> teste (devia a saída padrão do valor de "n" a cada loop para o arquivo "teste")
done (feito)
Obs: o loop acima é equivalente a "for n in $(seq 1 5); do echo $n >> teste; done" . Para obter ajuda digite "help for".



FOR ou SELECT (loop com base de dados em arquivo)
exemplo1:
for i in $(cat /tmp/test.txt)
do (faça)
echo $i
done (feito)
Obs: o loop acima é equivalente a "for i in $(cat /tmp/test.txt); do echo "$i"; done". Para obter ajuda digite "help for".



CASE (mútiplas opções)
exemplo1:
echo Escolha a opção 1 ou 2: ()
read NUM ()
case $NUM in ()
1) ()
echo O número é 1;;
2) ()
echo O número é 2;;
*) ()
echo O número não é 1 nem 2;;
esac ()
Obs: As múltiplas opções acima são equivalentes a "echo Escolha a opção 1 ou 2: ; read NUM ; case $NUM in 1) echo O número é 1;; 2) echo O número é 2;; *) echo O número não é 1 nem 2;; esac" . Para obter ajuda digite "help case".



Argumentos usados geralmente com "if", "while", for etc.
-b file True if the file exists and is block special file.
-c file (True if the file exists and is character special file)
-d file (True if the file exists and is a directory)
-e file (True if the file exists)
-f file (True if the file exists and is a regular file)
-g file (True if the file exists and the set-group-id bit is set)
-k file (True if the file exists and the "sticky" bit is set)
-L file (True if the file exists and is a symbolic link)
-p file (True if the file exists and is a named pipe. "named_pipes" são usados na comunicação entre processos que estão na memória. Quando dois processos precisam se comunicar/trocar informações é usado um intermediário chamado "named_pipe". No FreeBSD e no GNU/Linux um "named_pipe" é um arquivo onde um processo "escreve" e outro "ler" [FIFO])
-r file (True if the file exists and is readable)
-s file (True if the file exists and its size is greater than zero)
-S file (True if the file exists and is a socket)
-t fd (True if the file descriptor is opened on a terminal)
-u file (True if the file exists and its set-user-id bit is set)
-w file (True if the file exists and is writable)
-x file (True if the file exists and is executable)
-O file (True if the file exists and is owned by the effective user id)
-G file (True if the file exists and is owned by the effective group id)
-n string (True if the length of the string is non-zero)
-z string (True if the length of the string is 0)
file1 –nt file2 (True if file1 is newer, by modification date, than file2)
file1 ot file2 (True if file1 is older than file2)
file1 ef file2 (True if file1 and file2 have the same device and inode numbers)
string1 = string2 (True if the strings are equal)
string1 != string2 (True if the strings are not equal)
!expr (True if the expr evaluates to false)
expr1 –a expr2 (True if both expr1 and expr2 are true)
expr1 –o expr2 (True is either expr1 or expr2 is true)
-lt ( é menor que? )
-gt ( é maior que? )
-le ( é menor ou igual a? )
-ge ( é maior ou igual a? )
-eq ( é igual a? )
-ne ( é diferente de? )
= ( é igual a? )
!= ( é diferente de? )
-n ( existe? )
-z ( é nula? )
! ( not )
-a ( and )
-o ( or )


ARRAY (vetor)
exemplo1:
names=(hugo luciana hudson thaise bia)
echo $names (ERRADO, pois mostrara somente o primerio item do array que e "hugo")
echo ${names[*]} (mostrara todo o conteudo que e "hugo luciana hudson thaise bia")
echo ${names[@]} (idem)
echo ${#names[*]} (mostra a quantidade de posicoes no vetor/array para armazenar as variaveis)
echo ${#names[@]} (idem)
echo ${names[0]} (mostrara o primeiro item do array que e "hugo")
echo ${names[1]} (mostrara o segundo item do array que e "luciana")
echo ${names[2]} (mostrara o terceiro item do array que e "hudson")
echo ${#names[0]} (mostrara a quantidade de caracteres do primeiro item do array que e "hugo")
echo ${#names[1]} (mostrara a quantidade de caracteres do segundo item do array que e "luciana")
echo ${#names[2]} (mostrara a quantidade de caracteres do terceiro item do array que e "hudson")
set | grep names (RESULTADO: names=([0]="hugo" [1]="luciana" [2]="hudson" [3]="thaise" [4]="bia"))


ARRAY + FOR (vetor)
exemplo1:
names=(hugo luciana hudson thaise bia)
for name in ${names[@]} ()
do
echo $name
done


ARRAY + FOR (vetor)
exemplo2:
names=(hugo luciana hudson thaise bia)
for (( i = 0 ; i < ${#names[@]} ; i++ )) ()
do
echo ${names[$i]}
done


ARRAY + FOR (vetor)
exemplo3:
()



FUNÇÃO

Como em tantas linguagens de programação, no shell também existe a chamada de sistema conhecida como FUNÇÂO. A seguir se tem a sintax para a criação de uma função no shell:

function nome_função() { minha_função; }

Com esta declaração anterior criamos uma função "function" chamada "nome_função" onde as instruções/procedimentos que devem ser feitos estão englobadas em "minha_função". Abaixo, veja duas outras formas de fazer a mesma coisa, sendo que o único caractere que não é necessário é o ";" (ponto e vírgula).

function nome_função() (idem, mas com identação)
{
minha_função
}
------------------------------
nome_função() (idem, pois o termo "function" é opcional)
{
minha_função
}
Obs: como foi dito, o termo "function" é opcional, contudo é sempre visualmente melhor colocá-lo e nesse artigo ele será sempre evidenciado.

Depois de declarada uma função, para usá-la basta digitar o seu nome como se fosse um comando, pois no bash a função é chamada utilizando o seu nome. Não use o () para chamá-la, use somente o nome da função. Geralmente a função é usada dentro de scripts para resolver algum problema. A função deve ser declara antes de ser usada. Sempre é mais organizado declará-las no início do script.

Prática


Veja como o bash guardou a função anterior


Obs: muito cuidade para não dar o nome de algum comando para as funções, pois a função terá precedência. Por exemplo, se der o nome "grep" para uma função, não consiguiremos mais usar o comando de tal nome. Caso isso aconteça e não for possível mudar o nome da função por algum motivo, faça GREP=$(which grep) ou utilize o caminho completo do comando "/bin/grep". Caso o nome dado a função seja um comando interno do bash (ex: cd), utilize o comando "builtin" ou o "\"(ex: builtin cd ou \cd) para executar.


Passando argumentos:
minha_função arg1 arg2 arg3

Passando argumentos na prática:



Retorno da função (inteiros)

Para retornar algo da função é utilizado o comando "return". Ele só pode retornar inteiros. Outros tipos podem ser usados no shell, mas não usando o "return". No exemplo a seguir, vamos usar o '0' quando for verdade e o '1' quando não for verdade. Veja que ela testa se foi passado algum argumento ou não.




Retorno da função (string)

Retornando um string. No exemplo a seguir, vamos usar o 'verdade' quando for verdade e o 'mentira' quando não for verdade. Veja que ela testa se foi passado algum argumento ou não.


Variável Global, Local e Constante dentro de uma função

Primeiramente devemos diferenciar uma variável (global e local) usada dentro de uma função de uma variável de ambiente usada no bash. A variável usada dentro de uma função normalmente está contida em um script e vem para armazernar algum valor que deve ser usado pelas funções que estão dentro desse script. Já a variável de ambiente é usada pelos usuários ou serviços do sistema, utilizando na maioria da vezes o comando "export" para criá-las.

Variável global em uma função, é uma variável que têm o objetivo de ser visualizada por qualquer função dentro de um script. Variável local, é uma variável que é visualizada somente dentro da função que a declarou, ou seja, só é válida dentro do escopo da função que a criou. Constante, é um valor que não pode ser mudado.

Para declarar uma váriável global, é só declarar em qualquer parte do script, menos dentro de uma função. Prefira declarar no início do script. Ex:

# vi dados.sh (abrir um arquivo chamado dados.sh com o "vi")
HUGO='30 anos'
FLAMENGO='Campeão'

Para declarar uma váriável local, é só declarar dentro de uma função. Prefira declarar uma variável local no início da função. Além disso, devemos colocar a palavra "local" antes do nome da variável. Ex:

# vi dados.sh (abrir um arquivo chamado dados.sh com o "vi")
function nome_função()
{
local HUGO='25 anos'
local FLAMENGO='Campeão'
echo $HUGO
echo $FLAMENGO
}

Algo muito importante a ser dito em relação a variável global e local é a precedência. Em outras palavras, se for declarada a variável 'HUGO=30 anos' globalmente e 'HUGO=25 anos' localmente, ao chamarmos essa variável fora da função ele terá o valor igual a '30 anos' e se a chamarmos usando a função ela terá o valor igual a '25 anos'. Ex:

# vi dados.sh
HUGO='30 anos'
FLAMENGO='Campeão'
function nome_funcao()
{
local HUGO='25 anos'
local FLAMENGO='Vice-Campeão'
echo $HUGO
echo $FLAMENGO
}

Agora, execute no shell:

# source dados.sh
# echo $HUGO
30 anos
# echo $FLAMENGO
Campeão
# nome_funcao
25 anos
Vice-Campeão

Vamos agora ver como declararmos uma contante. Primeiramente será declarada uma constante global, seguindo a sintaxe "declare -r <nome_da_constante>=<valor>":

# vi dados.sh (abrir um arquivo chamado dados.sh com o "vi")
declare -r hora='24horas' (a opção "-r" informa que a variável é somente leitura. Se tentar mudar o seu valor, um erro será retornado "readonly variable")

Agora veremos como declararmos uma contante local, seguindo a sintaxe "local -r <nome_da_constante>=<valor>":

# vi dados.sh (abrir um arquivo chamado dados.sh com o "vi")
function nome_função()
{
local -r HUGO='brasileiro' (a opção "-r" informa que a variável é somente leitura. Se tentar mudar o seu valor, um erro será retornado "readonly variable")
local -r FLAMENGO='Campeão'
echo $HUGO
echo $FLAMENGO
}

O comando para ver as funcoes disponiveis e:

# declare -f



Referências Bibliográgicas
MOTA FILHO, J. E. Descobrindo o linux: entenda o sistema operacional GNU/Linux. 2. ed. São Paulo: Novatec, 2007.
http://www.vivaolinux.com.br/artigo/Como-trabalhar-com-funcoes-em-bash/
 
 




ETI - Especialista em Tecnologia
da Informação