Escolar Documentos
Profissional Documentos
Cultura Documentos
arktec.com.br ABRIR
Dando continuidade ao Curso de Shell Script, neste segundo módulo vou mostrar como criar scripts Shell. Caso não tenha visto o primeiro módulo,
acesse este link para ler o Curso de Shell Script: Módulo #0 – Comandos Básicos do Linux.
NOTA: O conteúdo deste post foi aprimorado e somado a diversos outros temas ligados à Programação usando Shell Script. Tudo isso resultou no
curso “Shell Script Para Programadores“. Conheço melhor o curso neste link.
Este curso de Shell Script está dividiso em dois módulos. São eles:
Módulo #0: Comandos Básicos do Linux: primeiro módulo, onde mostro quais são os principais comandos do Bash (utilizáveis em Linux e Mac
OS X)
Módulo #1: Scripts Shell e suas estruturas: este módulo, onde mostro como estruturar scripts Shell, usando o conhecimento do Módulo #0 do
Curso de Shell Script
Neste módulo, vou mostrar vários conceitos da Programação em Shell (Bash), desde variáveis e funções, até expansões, expressões regulares, criação
de funções etc.
Sumário
0. Scripts Shell
1. Variáveis
1.1 Variáveis de Ambiente
1.2. Variáveis Especiais
2. Controle de Fluxo
2.1. Condicionais
2.1.1. if
2.1.2. case
2.1.3. select
2.2. Estruturas de Repetição (Loops)
2.2.1. for
2.2.2. while
2.2.3. until…do
2.2.4. break
2.2.5. continue
3. Padrão C/C++ em Expressões “(())”
4. Entrada/Saída
4.1. Redirecionamento
4.2. Usando Pipelines
5. Expansões
5.1. Expansão de Variáveis
6. Parâmetros de linha de comando
7. De nindo Funções
7.1. Retorno de Funções
8. Expressões Regulares em Bash
9. Expressões Matemáticas
10. O Arquivo .bashrc
11. Aliases (Apelidos)
12. Para onde ir agora?
0. Scripts Shell
Antes de mostrar os recursos do shell, vamos dar uma olhada na maneira como devemos criar scripts shell. Isso facilitará a compreensão do restante
do artigo.
Todo arquivo com códigos shell deve ter, na primeira linha, o identi cador do interpretador a ser utilizado. A “linha mágica” que chama o interpretado
bash é:
#!/bin/bash
O mesmo vale para outras linguagens interpretadas, como PHP, Python, Ruby, Perl etc.
Tendo essa linha no início do arquivo, o segundo passo é dar permissão de execução ao arquivo:
$ chmod +x script.sh
$ ./script.sh
$ bash script.sh
Assim não é necessário haver a “linha mágica” no início do script. Também não é preciso dar permissão de execução ao arquivo.
1. Variáveis
O Bash, assim como muitas outras linguagens, possui o conceito de variável. Para de nir uma variável:
nome_da_variavel="valor da variável"
É importante ressaltar que não deve haver espaços entre o símbolo de atribuição, o nome da variável e seu valor, para que o bash interprete o
comando como atribuição, não chamada de comandos.
Para exibir o valor de uma variável, basta usar echo da seguinte forma:
echo $nome_da_variavel
Para entender o seu uso, vejamos um exemplo: editores de texto, como Vi, possuem diferentes interfaces para os modos texto e grá co e necessitam
saber qual o tipo de terminal o usuário está usando. A variável de ambiente TERM é o modo pelo qual isto pode ser determinado. Outro exemplo são
os programas de e-mail que permitem ao usuário editar mensagens com o editor de textos de sua preferência. Como estes programas sabem qual
editor usar? É através da variável EDITOR ou VISUAL.
Qualquer variável pode se tornar uma variável de ambiente. Para isto, ela deve ser “exportada”, com o comando export:
export <variável>
Também podemos exportar e atribuir valores a uma variável numa única linha de comando:
export <variável>=
Podemos veri car quais são as variáveis de ambiente já de nidas e seus respectivos valores usando o comando abaixo:
export -p
Para visualizar todas as variáveis basta usar set ou env. Uma importante variável de ambiente é PATH que ajuda o shell a encontrar os comandos que
o usuário executa. Todo comando executado é, na realidade, um arquivo. Estes arquivos são chamados executáveis e estão armazenados em vários
diretórios como /bin ou /usr/bin. O valor da variável PATH é uma lista de diretórios em que o shell procura toda vez que executamos um comando
cujo arquivo não é encontrado no diretório corrente. Assim, não precisamos alterar o diretório de trabalho todas vez que necessitamos executar um
comando que se encontra em outro diretório. Basta acrescentar o diretório que contém tal comando à variável PATH. Os nomes dos diretórios na
variável são separados pelo caractere dois-pontos (:).
Caso o usuário joao queira adicionar um outro diretório, digamos /home/joao/bin à variável PATH, deve proceder como mostrado a seguir:
O primeiro comando faz com que a variável receba o seu valor atual, concatenado com o nome do diretório a ser acrescentado. Observe que existe
um “:” antes do nome do diretório. O segundo comando é utilizado apenas para visualizarmos o resultado do primeiro.
Este trecho do artigo está disponível apenas para alunos do meu curso Shell Script Para Programadores. Para conhecer melhor o curso e fazer sua
matrícula, clique aqui
[cta id=’925′]
2. Controle de Fluxo
Controle de uxo permite interromper, continuar e deslocar o uxo de execução do script. Isso envolve controles de decisão (condicionais) e
estruturas de repetição (loops).
2.1. Condicionais
2.1.1. if
Sintaxe:
if
then
comandos
elif
comandos
else
comandos
fi
O if, ao contrário do que ocorre em muitas outras linguagens, testa o retorno de um comando, não uma expressão.
Por exemplo:
if test 5 -lt 7
then
echo '5 é menor que 7'
fi
Porém, é possível posicionar a expressão entre colchetes, de forma a tornar o if mais parecido com o que acontece em outras linguagens:
if [ 5 -lt 7 ]
then
echo '5 é menor que 7'
fi
O “-lt” signi ca “less than“, ou seja, “menor que“, equivalendo ao operador “<". Outros possíveis operadores são: Comparação Numérica
-lt: É menor que (LessThan)
-gt: É maior que (GreaterThan)
-le: É menor igual (LessEqual)
-ge: É maior igual (GreaterEqual)
-eq: É igual (EQual)
-ne: É diferente (NotEqual)
Comparação de Strings
=: É igual
!=: É diferente
-n: É não nula (não vazia)
-z: É nula (vazia)
Operadores Lógicos
!: NÃO lógico (NOT)
-a: E lógico (AND)
-o: OU lógico (OR)
Testes em arquivos
-b: É um dispositivo de bloco
-c: É um dispositivo de caractere
-d: É um diretório
-e: O arquivo existe
-f: É um arquivo normal
-g: O bit SGID está ativado
-G: O grupo do arquivo é o do usuário atual
-k: O sticky-bit está ativado
-L: O arquivo é um link simbólico
-O: O dono do arquivo é o usuário atual
-p: O arquivo é um named pipe
-r: O arquivo tem permissão de leitura
-s: O tamanho do arquivo é maior que zero
-S: O arquivo é um socket
-t: O descritor de arquivos N é um terminal
-u: O bit SUID está ativado
-w: O arquivo tem permissão de escrita
-x: O arquivo tem permissão de execução
-nt: O arquivo é mais recente (NewerThan)
-ot: O arquivo é mais antigo (OlderThan)
-ef: O arquivo é o mesmo (EqualFile)
2.1.2. case
Sintaxe:
case in
opcao1)
comandos
;;
opcao2)
comandos
;;
*)
operação padrão
esac
Exemplo:
case "$x" in
1)
echo "Você digitou o número 1"
;;
2)
echo "Você digitou o número 2"
;;
*)
echo "Você digitou outro número"
esac
2.1.3. select
Sintaxe:
select in ...
do
comandos
done
O comando select é pouco utilizado, mas pode ser muito útil para montar menus. Esse comando exibe um menu, associando cada opção a um
número. Quando o usuário seleciona o número da opção, o seu valor é associado à .
Exemplo:
Loops são estruturas que permitem fazer iterações sobre algum dado.
2.2.1. for
Sintaxe:
for <var> in
do
done
</var>
“var” é o nome da variável a ser usada no bloco de repetição. “lista” pode ser uma lista de dados, xa ou retornada por outro comando (como o ls),
uma sequência de números etc.
Exemplos:
for i in 1 2 3 4 5
do
echo $i
done
2.2.2. while
Sintaxe:
while
do
done
Exemplos:
i=0
while [ $i -lt 10 ]
do
echo $i
i=$((i+1))
done
while true
do
echo 'bash'
done
while read i
do
echo 'Voce digitou a string: ' $i
done
Esse exemplo facilita o trabalho com arquivos de texto, cujas linhas possuem espaços. Se fosse usado um loop for nesse caso, seria necessário alterar
a variável de ambiente IFS, de nindo o separador para quebra de linha (\n).
while read i
do
echo $i
done < arquivo.txt
A principal diferença entre estes dois últimos exemplos é que, no primeiro, o loop while é executado num subshell, devido ao uso do pipe (|). No
segundo exemplo, o while é executado no shell corrente.
Para ilustrar o problema, crie um arquivo chamado “arq.txt” com algumas linhas de texto. Crie este script e execute-o:
#!/bin/bash
FILE='arq.txt'
total=0
cat $FILE | while read i
do
total=$((total+1))
done
echo 'Total de linhas: ' $total
total=0
while read i
do
total=$((total+1))
done < $FILE
echo 'Total de linhas: ' $total
O primeiro loop é executado num subshell, fazendo com que a variável “total”, usada no corpo do loop, existe apenas nesse subshell. No segundo
caso, isso não ocorre. Isso pode gerar grandes dores de cabeça… (como já ocorreu comigo)
2.2.3. until…do
Sintaxe:
until
do
done
Com while:
i=0
while [ $i -lt 10 ]
do
echo $i
i=$((i+1))
done
Com unitl:
i=0
until [ $i -ge 10 ]
do
echo $i
i=$((i+1))
done
Para fazer a mesma coisa, tivemos que usar expressões diferentes na condição do loop.
2.2.4. break
Exemplos:
i=0
while true
do
if [ $i -ge 10 ]
then
break
fi
i=$((i+1))
done
while read i
do
if [ $i -eq 0 ]
then
break
fi
done
2.2.5. continue
O comando continue para a execução da iteração corrente e vai para a próxima iteração, mesmo que haja mais comandos no bloco de repetição.
3. Padrão C/C++ em Expressões “(())”
É possível usar o padrão C em expressões do shell, como em condicionais de estruturas de controle. Para isso, basta colocar a expressão entre dois
parênteses.
Exemplos;
i=0
while (( i < 10 ))
do
echo $i
((i++))
done
4. Entrada/Saída
Existem três dispositivos principais, que sempre estão abertos, que merecem destaque:
Esses três dispositivos estão em /dev e estão sempre disponíveis. Quem programa em C, sabe muito bem disso, pois já deve ter usado stdin, stdout e
stderr junto com fprintf, fread, fwrite e semelhantes; esses três dispositivos comportam-se como arquivos comuns, sempre abertos e que não devem
ser fechados.
É possível brincar com eles no próprio shell. Experimentem dar um cat em /dev/stdin para ver o que acontece. :)
4.1. Redirecionamento
A entrada de um programa consiste nos dados que lhe são passados inicialmente, os quais são necessários para a execução do programa. A entrada
de um programa pode vir do teclado ou de um arquivo, por exemplo. Argumentos passados à comandos constituem a sua entrada.
A saída é constituída pelas informações geradas pelo programa, ou seja, o resultado de sua execução. A saída pode ser mostrada na tela ou gravada
em um arquivo de registro.
Muitos comandos do Linux têm sua entrada con gurada para a entrada padrão e sua saída para a saída padrão. A entrada padrão é o teclado e a
saída padrão é o monitor. Vejamos um exemplo usando o comando cat, que lê dados de todos os arquivos passados como parâmetros e os envia
diretamente para a saída padrão. Usando o comando abaixo, veremos o conteúdo do arquivo “arq1” seguido pelo conteúdo de “arq2”.
Entretanto, se nenhum nome de arquivo for dado como parâmetro, o comando cat lê dados da entrada padrão e os envia para a saída padrão. Para
interromper, deve-se pressionar as teclas ctrl e d simultaneamente (ctrl+d).
$ cat
Ola! Tem alguem ai? # usuário
Ola! Tem alguem ai? # eco do sistema
Ate mais! # usuário
Ate mais! # eco do sistema
# usuário pressiona ctrl+d
Como podemos ver, cada linha que o usuário digita é imediatamente ecoada pelo comando cat. Aqui um outro exemplo: o comando sort lê dados da
entrada padrão – a menos que algum arquivo seja dado como parâmetro – e ordena os dados, enviando-os para a saída padrão:
$ sort
bananas # usuário
peras # usuário
goiabas # usuário
# ctrl+d
bananas # eco do sistema
goiabas # eco do sistema
peras # eco do sistema
Digamos que queremos enviar a saída do comando sort para um arquivo, gravando os dados digitados anteriormente. O shell nos permite
redirecionar a saída para um arquivo usando o símbolo “>”.
Como se pode ver, o resultado do comando sort não é mostrado imediatamente após o se digitar ctrl+d. Ao invés disso, é salvo em um arquivo
chamado “lista”. Vejamos o conteúdo desse arquivo:
$ cat lista
bananas
goiabas
peras
Com o redirecionamento de saída, temos uma maneira simples de criar arquivos de texto. Para isso, utilizamos o comando cat para ler a entrada
padrão (teclado) e redirecionamos sua saída para um arquivo.
Ao usar “>” para redirecionar a saída para um arquivo, estamos realizando um redirecionamento destrutivo, ou seja, o comando “ls > lista” sobrescreve
o conteúdo do arquivo “lista”. Isto é equivalente a dizer que todo o conteúdo anterior de “lista” é apagado.
Se, ao invés disso, redirecionarmos usando “>>”, a saída será concatenada ao nal do arquivo e o conteúdo (se houver) de “lista” será preservado. Para
melhor entender isso, experimente executar a seguinte seqüência de comandos:
ls >> listagem
ls >> listagem
less listagem
Nos exemplos para o ltro sort, os dados de entrada eram digitados pelo usuário ou estavam gravados em um arquivo. O que aconteceria se
quiséssemos ordenar dados vindos do saída de outro comando ? Para listar os arquivos do diretório corrente em ordem alfabética invertida devemos
fazer com que a saída do comando ls seja ordenada pelo comando sort. Usando a opção “-r”, este comando ordena os dados na ordem inversa.
$ ls
historia notas tese testes
$ ls > lista
$ sort -r lista
testes
tese
notas
lista # observe esse nome de arquivo
historia
Aqui, salvamos a saída do comando ls em um arquivo (lista) e usamos sort com a opção “-r”. Porém, isso faz com que tenhamos um arquivo
temporário para armazenar os dados. Assim, toda vez que zermos isso, teremos que, em seguida, remover o arquivo lista. A solução é usar o que
chamamos de pipeline, outro recurso do shell que nos permite conectar vários comandos usando um pipe, onde a saída do primeiro comando é
enviada diretamente à entrada do segundo e assim por diante no caso de haver mais de dois comandos conectados por pipes.
No nosso caso, queremos enviar a saída do comando ls para a entrada do comando sort. O símbolo “|” (barra vertical) é usado para criar um pipe:
$ ls | sort -r
testes
tese
notas
historia
Note que neste exemplo, nenhum nome de arquivo é usado na linha de comando, diferentemente do exemplo anterior que fazia o uso do arquivo
intermediário lista. Outra diferença é que o nome desse arquivo intermediário aparece no resultado do penúltimo exemplo, mas não neste último. O
comando é mais curto, mais fácil de digitar e o resultado é mais adequado pois não inclui nomes de arquivos intermediários.
É importante observar que o redirecionamento e o uso de pipes são características do shell e não dos comandos em si. É o shell quem provê a sintaxe
dos símbolos “>”, “<" e "|". Logo, se você criar um programa que utilize entrada de dados via stdin, poderá usar redirecionamento para especi car uma
entrada para o seu programa. [cta id='925']
5. Expansões
Este trecho do artigo está disponível apenas para alunos do meu curso Shell Script Para Programadores. Para conhecer melhor o curso e fazer sua
matrícula, clique aqui
Este trecho do artigo está disponível apenas para alunos do meu curso Shell Script Para Programadores. Para conhecer melhor o curso e fazer sua
matrícula, clique aqui
Assim como em outras linguagens, é possível passar parâmetros para scripts shell. Para isso, usam-se as variáveis $1, $2, … A variável $0 contém o
comando chamado via linha de comando.
Exemplo:
#!/bin/bash
$ ./test.sh
$0 = ./test.sh
$1 =
$2 =
$ ./test.sh um
$0 = ./test.sh
$1 = um
$2 =
$ ./test.sh um dois
$0 = ./test.sh
$1 = um
$2 = dois
7. De nindo Funções
Sintaxe:
function nome_da_funcao()
{
nome_da_funcao
Exemplo:
#!/bin/bash
function imprime()
{
echo "Sou a função '${0}'"
echo "Param 1: ${1}"
echo "Param 2: ${2}"
echo "Lista de parâmetros: ${*}"
}
Antes de tudo, é preciso diferenciar retorno de função e saída de função. Por exemplo, ao se executar o comando “cat /etc/passwd”, a saída é o
conteúdo do arquivo; o retorno é 0 (ou outro valor, caso ocorra erro). O retorno de uma função shell é um valor inteiro, normalmente utilizado para
de nir o status da função, ou seja, se ocorreu algum erro ou e ela foi executada corretamente.
Para obter o valor de retorno de uma função, usa-se a variável “$?”. Ela exibe o retorno do último comando executado. Por exemplo:
$ cat /etc/passwd
echo $?
Exemplo:
#!/bin/bash
function retorna()
{
echo "sou um valor"
return 42
}
valor=$(retorna)
echo $?
echo $valor
Ao se executar a função, sua saída será “sou um valor”; seu retorno será 42.
Em shell, considera-se o valor 0 como execução bem sucedida. Qualquer outro valor representa erro. É por isso que recomenda-se que toda função
main de um programa em C retorne o valor 0, desde que não ocorra algum erro.
Este trecho do artigo está disponível apenas para alunos do meu curso Shell Script Para Programadores. Para conhecer melhor o curso e fazer sua
matrícula, clique aqui
9. Expressões Matemáticas
O bash não trabalha com expressões matemáticas tão facilmente. Existe o comando “let”, que permite realizar expressões matemáticas, mas é mais
comum se usar a sintaxe semelhante ao C, utilizando dois parênteses:
$ a=$((1 + 1))
$ ((i++))
$ x=$((x*2))
...
Este trecho do artigo está disponível apenas para alunos do meu curso Shell Script Para Programadores. Para conhecer melhor o curso e fazer sua
matrícula, clique aqui
Algumas vezes usamos comandos que necessitam de várias opções e argumentos. Para amenizar o trabalho de digitarmos repetidamente estes
comandos o bash oferece um recurso chamado alias com o qual podemos de nir sinônimos ou “apelidos” para um comando. Um alias pode ser
de nido na linha de comando da seguinte forma:
alias =
Observe que não pode haver espaços em branco antes ou depois do “=”.
Esta sintaxe indica que nome é um “alias” (apelido) para comando. Toda vez que digitarmos o comando “nome”, o bash o substituirá por “comando”.
Exemplo:
Isso fará o shell executar “ls -F” toda vez que usarmos “lf” na linha de comando. Ou seja, o que o alias faz na verdade é substituir a palavra “lf” por “ls -
F”. Observe neste exemplo, existe um espaço em branco entre ls e -F. Sempre que houver espaços em branco na de nição de um campo, todo o
campo deve ser digitado entre aspas simples (‘) ou duplas (“).
É possível de nir aliases em seu .bashrc, para que eles estejam sempre disponíveis na sua sessão.
O mundo dos comandos e dos shell scripts é muito mais amplo! Eu mostrei aqui um pouco sobre ele, abordando as técnicas principais e mais usadas.
É possível ir muito mais além, criando scripts pro ssionais, que ajudam muito o dia-a-dia!
Para aprender mais sobre Comandos Linux e Shell Script, veja meu curso Shell Script Para Programadores.
Roberto Beraldo
Graduado em Ciência da Computação, pela Universidade Federal do Paraná (UFPR), é desenvolvedor de software desde 2008, com
foco em Desenvolvimento Web com PHP.
Anúncio
Guarda de documentos da Arktec - Mais de 25 Anos de Experiência
Relacionado
Composer: o gerenciador de Como Atualizar Scripts PHP de MySQL Enviando E-Mails com a Classe PHPMailer
dependências para PHP Para MySQLi 26/01/2011
11/06/2015 29/10/2015 Em "PHP"
Em "Dicas" Em "MySQL"
Este post foi publicado em Linux, Programação, Shell Script (Bash) e marcado com a tag Bash, curso, Linux, Programação, script, sh, Shell, Tutorial, unix
em 05/11/2011 [http://rberaldo.com.br/curso-de-shell-script-modulo-1-scripts-shell-estruturas/] .
Comentários Comunidade
1 Entrar
Iniciar a discussão...
Nome