sábado, 7 de junho de 2014

Programação com shell script

Este artigo destina-se aos que já conhecem o básico de lógica de programação e que estejam interessados em aprender shell script.

O shell script é uma linguagem de programação utilizada, principalmente, para automatizar tarefas administrativas em sistemas operacionais Unix-like.

Existem vários interpretadores para os scripts em shell, o mais utilizado em distribuições GNU/Linux é o bash. Além dele, outras opções de interpretadores são o sh, csh e o ksh.

Nesse artigo, a minha ideia é trabalhar apenas com shell script interpretado pelo bash (durante o artigo vou chamar apenas de shell script).

Para iniciar, vou usar o famoso: "Olá mundo!" (nesse caso: "ola user"). Com um editor de texto, criei o arquivo "teste.sh" com o seguinte conteúdo:

 
#!/bin/bash
echo "ola $USER";
 

Esse script simplesmente cumprimenta o usuário. Nele utilizei o comando "echo", que imprime na saída padrão ( nesse caso o monitor ), e a variável de ambiente "$USER", que guarda o usuário logado.

A primeira linha desse script, "#!/bin/bash", indica o interpretador que deve executar os comandos que estão no arquivo.

Poderia ser outro interpretador shell (como por exemplo o #!/bin/sh), ou até mesmo não ser especificado nenhum interpretador. Nesse caso, o sistema vai utilizar o interpretador que estiver na variável "$SHELL" (interpretador padrão).

Para testar este script, é necessário que ele tenha permissão de execução no sistema, para isso, supondo que o arquivo foi salvo no diretório atual, vou rodar no terminal o comando abaixo:


chmod +x teste.sh
 

e depois para executar o script vou usar o comando:


./teste.sh
 

Para executar esse script, eu especifiquei o caminho até o arquivo "teste.sh" (o "./" representa o diretório atual), isso foi necessário porque quando é digitado um comando (ou um script shell) no terminal, se não especificar o caminho até o arquivo, o sistema busca por ele nos diretórios que aparecem na variável "$PATH".

Se não quiser especificar o caminho para executar seus scripts, você pode colocá-los em um dos diretórios que aparecem na "$PATH" ou configurar o diretório onde eles estão nessa variável. ( exemplo de como fazer isso aqui ).

Assim como outras linguagens de programação, shell script possui estruturas de controle do tipo: if, case, while e for. A sintaxe dessas estruturas é a seguinte:

If
#!/bin/bash
nome="paulo";
if [ $nome != "paulo" ] ; then

  echo "vc não é o paulo!";
fi
 
Case
#!/bin/bash
i=1;
case $i in 

 1)
    echo "é 1";
 ;;
 
 2)
    echo "é 2";
 ;;

 *) 
    echo "não eh 1 nem 2";
 ;;
esac

While
#!/bin/bash
i=1;
while [ $i -le 10 ] ; do 

  echo $i;
  i=$(( $i + 1 ));
done

For
#!/bin/bash
for i in $( seq 10 ) ; do 

  echo $i;
done 

Shell script tem algumas características que não são comuns em outras linguagens. Por exemplo, os espaçamentos que normalmente são permitidos em outras linguagens, podem causar erros em shell script.

Quando é criada uma variável, não deve haver espaços entre o nome da variável, o sinal de igual e o valor atribuído:

#!/bin/bash
i=1;   # ok, vai funcionar
j = 2; # não vai funcionar

Observações:

1 - Perceba que ao criar a variável, não usei o "$". Este símbolo é usado apenas para recuperar o valor da variável.
2 - O que está após o símbolo "#" é considerado comentário e não é executado.
3 - É possível utilizar o comando read para ler da entrada padrão (geralmente o teclado) e criar variáveis especificadas pelo usuário em tempo de execução.

Outra particularidade do shell script é que operações matemáticas não são realizadas diretamente, é necessário utilizar algum comando para realizar o calculo, por exemplo:

#!/bin/bash
i=1;   
j=$(( $i + 1 ));    # ok
j=$( expr $i + 2 ); # ok
j=$i + 1;           # não vai funcionar como esperado

Nesse exemplo foi utilizado o comando "$( expr $i + 2 )", basicamente trata-se de um sub-shell, o que estiver dentro de "$( )" é executado à parte e o resultado( o que seria impresso na saída padrão) é atribuído para variável. Também seria possível utilizar o comando "` expr $i + 2 `" para ter o mesmo resultado.

Outro detalhe importante que foi visto nos exemplos anteriores são os operadores usados nas estruturas de controle dentro do comando "[ ]", que na verdade é um açúcar sintático para o comando "test", veja alguns exemplos de operadores:

Para Numeros
-lt É menor que (LessThan)
-gt É maior que (GreaterThan)
-le É menor ou igual (LessEqual)
-ge É maior ou igual (GreaterEqual)
-eq É igual (EQual)
-ne É diferente (NotEqual)
Para Strings
= É igual
!= É diferente
Testes logicos
! Negação
-a and ( geralmente && )
-o or( geralmente || )
Shell script também tem funções, elas seguem a seguinte sintaxe:
#!/bin/bash

function somar() {

  echo $(( $1 + $2 ));  
}

somar 1 2

As funções em shell script são chamadas da mesma forma que um comando, elas recebem parâmetros sem a necessidade de especificá-los na declaração da função. Os parâmetros são recuperados através de variáveis especais, como a "$1" e a "$2" utilizadas no exemplo acima. Veja outras dessas variáveis especiais:

$0 O nome da função
$1 O primeiro parâmetro
$2 O segundo parâmetro
$numero O parâmetro da posição numero
$# A quantidade de parâmetros
$* Todos os parâmetros

Com essas variáveis, posso melhorar o script anterior de forma a não limitar o número de parâmetros a serem somados:

#!/bin/bash

function somar() {

  resultado=0;
  for i in $* ; do

    resultado=$(( $resultado + $i ));
  done

  echo $resultado;
}

somar 1 2 3 4 5

Uma observação importante sobre as funções em shell script é que apesar de possuir a instrução "return", essa instrução é utilizada de uma forma diferente.

Em shell script funções são como os comandos, os comandos tem um código de retorno que indica se o comando foi executado corretamente ou não( isso é testado com a variável "$?" ), portanto as funções também tem esse código de retorno, que é retornado com a instrução "return" :)

Para conseguir armazenar o retorno de função em uma variável costumo usar o sub-shell:

#!/bin/bash

function somar() {

  resultado=0;
  for i in $* ; do

    resultado=$(( $resultado + $i ));
  done

  echo $resultado;
}

#usando o sub-shell é possível 
#armazenar o retorno da função 
total=$( somar 1 2 3 4 5 );

A grande utilidade das funções, é que elas organizam e garantem a reutilização de código. Uma possibilidade interessante que o shell script permite, é incluir um arquivo com funções dentro de outro (parecido com o require e include do PHP).

Por exemplo, posso criar varias funções que estejam relacionadas e colocá-las no mesmo arquivo e depois, quando for necessário, uso a instrução "source" para incluir essas funções em outro arquivo.

Supondo que a função "somar" está no arquivo "matemática.sh", posso usá-la em outro arquivo da seguinte maneira:

#!/bin/bash

source "matematica.sh";

total=$( somar 1 2 3 4 5 );

Além de funções e estruturas de controle, Shell Script também possui arrays. Os arrays têm a seguinte sintaxe:

#!/bin/bash

dias=( "domingo" "segunda" "terca" "quarta" "quinta" "sexta" "sabado" );

echo ${dias[1]}; # imprime segunda

nomes[0]="paulo";
nomes[1]="ana";
nomes[2]="carlos";

echo ${nomes[1]}; 

# para retornar a quantidade de itens
echo ${#nomes[@]}  # imprime 3

Perceba que é possível criar arrays de duas formas diferentes, e que, para retornar o valor de uma posição do array, a sintaxe é diferente de uma variável comum.

Além disso, na última linha é feita a leitura da quantidade de itens (posições ocupadas) do array.

Vou terminar deixando um script com o que foi visto nesse artigo, se quiser saber mais sobre Shell Script veja os links mais abaixo. Até mais... :)

#!/bin/bash
function organiza() {

 array=($@);
 i=0;
 while [ $i -lt ${#array[@]} ]; do

    j=$(($i + 1));
    while [ $j -lt ${#array[@]} ]; do
   
       if [ ${array[$j]} -lt ${array[$i]} ]; then 
   
          aux=${array[$j]};
          array[$j]=${array[$i]};
          array[$i]=$aux;   
       fi 
       j=$(($j + 1));
    done
    i=$(($i + 1));
 done

 for n in ${array[@]}; do

    echo "$n";
 done
}

organiza 2 9 4 5 6 1 

Mais Informações:
http://thobias.org/doc/shell_bd.html
http://thobias.org/doc/cgi_shell.html
Paulo Dias | blog: http://blog.prmsistemas.com/

Nenhum comentário:

Postar um comentário