SlideShare uma empresa Scribd logo
1 de 27
Baixar para ler offline
Curso de Shell - Aula I
Introdução
O que são os shell scripts? Shell scripts são conjuntos de comandos armazenados em um
arquivo texto que são executados seqüencialmente. Nesta primeira parte, faremos uma
introdução sobre o shell, o formato desses arquivos e variáveis de ambiente.
O que é Shell
Shell, ou interpretador de comandos, é o programa disparado logo após o login responsável por
"pegar" os comandos do usuário, interpretá-los e executar uma determinada ação.
Por exemplo, quando você escreve no console "ls" e pressiona , o shell lê essa string e verifica
se existe algum comando interno (embutido no próprio shell) com esse nome. Se houver, ele
executa esse comando interno. Caso contrário, ele vai procurar no PATH por algum programa
que tenha esse nome. Se encontrar, ele executa esse programa, caso contrário, ele retorna uma
mensagem de erro. Para cada terminal ou console aberto, existe um shell sendo executado.
Quando você entra no seu Linux, ele apresenta o login, para digitar o usuário e a senha. Ao
digitar um par usuário/senha correto, o Linux abre automaticamente um shell, que vai ficar
esperando seus comandos. Veja o exemplo abaixo:
Welcome to Linux Slackware 7.1 kernel 2.2.16.
matrix login: neo
Password:
Linux 2.2.16.
Last login: Mon Sep 25 10:41:12 -0300 2000 on tty1.
No mail.
neo@matrix:~$
Essa ultima linha é o shell. Se você der o comando "ps", vai ver que um dos programas rodando
é o seu shell:
neo@matrix:~$ ps
PID TTY TIME CMD
164 tty2 00:00:00 bash
213 tty2 00:00:00 ps
neo@matrix:~$
Ou seja, o shell utilizado nesse console é o bash, que está rodando com PID 164.
Existem diversos tipos de shell: bash, csh, ksh, ash, etc. O mais utilizado atualmente é o bash
(GNU Bourne-Again SHell). Por isso, tomaremos ele como referência.
Resumindo essa seção, é importante saber que para cada terminal ou console aberto, tem-se
um shell rodando. Assim, se você tem 3 xterms abertos na interface gráfica, vai ter um shell
para cada xterm.
Ao executar o shell script, o shell atual (no qual você deu o comando) abre um novo shell para
executar o script. Assim, os scripts são executados em um shell próprio (a menos que se
especifique, ao chamar o script, para executá-lo no shell atual). Isso será importante quando
formos tratar de variáveis de ambiente.
Variáveis do ambiente
Uma variável é onde o shell armazena determinados valores para utilização posterior.
Toda variável possui um nome e um valor associado a ela, podendo ser este último vazio. Para
listar as variáveis atualmente definidas no shell digite o comando set.
Para se definir uma variável, basta utilizar a síntaxe: nome_da_variável=valor. Por exemplo,
queremos definir uma variável chamada "cor" com o valor de "azul":
neo@matrix:~$ cor=azul
Para utilizar o valor de uma variável, é só colocar um sinal de "$" seguido do nome da variável -
o shell automaticamente substitui pelo valor da variável:
neo@matrix:~$ echo cor
cor
neo@matrix:~$ echo $cor
azul
Em alguns casos, é aconselhável colocar o nome da variável entre chaves ({}). Por exemplo, se
eu quero imprimir "azul-escuro", como faria? Simplesmente echo $cor-escuro ?? Não
funcionaria, pois o bash vai procurar uma variável de nome "cor-escuro". Portanto, temos que
colocar o nome "cor" entre chaves para delimitar o nome da variável:
neo@matrix:~$ echo ${cor}-escuro azul-escuro
Algumas variáveis já são predefinidas no shell, como o PATH, que, como foi dito antes,
armazena o caminho dos programas. Por exemplo, a minha variável PATH contém:
neo@matrix:~$ echo $PATH
/usr/local/bin:/usr/bin:
/bin: /usr/X11R6/bin:
/usr/openwin/bin:
/usr/games:
/opt/kde/bin:
/usr/share/texmf/bin:
/etc/script
Ou seja, quando digito um comando, como "ls", o shell vai começar a procurá-lo em
/usr/local/bin, se não encontrá-lo, vai procurar em /usr/bin e assim por diante. Repare que os
diretórios são separados por um sinal de dois pontos (:).
É importante destacar que o shell possui várias variáveis pré-definidas, ou seja, que possuem
um significado especial para ele, entre elas: PATH, PWD, PS1, PS2, USER e UID.
Assim, quando iniciamos um novo shell (ao executar o nosso script), essas variáveis especiais
são "herdadas" do shell pai (o que executou o shell filho). Outras variáveis definidas pelo
usuário, como a variável "cor" não são passadas do shell pai para o filho.
Quando o script terminar, o seu shell (shell filho) simplesmente desaparece e com ele também
as suas variáveis, liberando o espaço ocupado na memória.
Formato dos arquivos de Shell Script
A primeira linha de todo shell script deve começar com algo do tipo: #!/bin/bash, a qual indica
com qual shell deverá ser executado o script. Nesse exemplo, estamos falando para o shell atual
executar o script com o shell /bin/bash.Se quisermos que o nosso script seja executado com o
shell csh, devemos colocar nessa primeira linha: #!/bin/csh. Como usaremos o bash como
nosso shell de referência, todas as linhas dos nossos scripts começarão com #!/bin/bash.
Digamos que você executa freqüentemente o comando: find / -name file -print, que procura
na raiz (/) por um arquivo de nome "file". Só que é chato ficar digitando esse comando toda vez
que se quer procurar um arquivo.
Então vamos criar um shell script que contenha esse comando. Vamos chamar esse shell script
de "procura". Seu conteúdo fica assim:
#!/bin/bash
find / -name file -print
Pronto. Tornemos agora o arquivo executável: chmod 755 ./procura. Porém, ao tentar
executar o nosso script, teremos um problema.
./procura
Este script irá procurar por um arquivo chamado "file". Como especificar qual arquivo queremos
procurar? Seria ideal executarmos o nosso script seguido do nome do arquivo que queremos
procurar.
Por exemplo, queremos saber onde está o arquivo "netscape": ./procura netscape. É ai que
entram as "variáveis de parâmetro". Vamos substituir no nosso script a linha find / -name file
-print por find / -name $1 -print. Quando o bash lê a variável "$1", ele a substitui pelo
primeiro parâmetro passado na linha de comando para o nosso script. Então, se executamos
./procura netscape, a variável "$1" será substituída por "netscape", como a gente queria.
Repare que a variável "$2" conteria o segundo parâmetro passado para o script e assim por
diante. Sendo assim, qualquer comando colocado abaixo de find seria executado após ele. Esse
é o essencial do shell script: poder automatizar a execução de programas e comandos como se
estivessem sendo digitados diretamente no console ou terminal.
Conclusão
Na próxima aula do nosso curso de shell script iremos aprender alguns comandos especiais para
tornar nossos script mais poderosos, fazendo coisas mais elaboradas do que apenas executar
programas seqüencialmente. Entre eles, podemos destacar os comandos de laço, como "if",
"for", "while", "case" etc.
[por Alex Borro]
Curso de Shell - Aula II
Introdução
Na aula de hoje vamos falar sobre execução de programas em primeiro plano (fg - foreground) e
em segundo plano (bg - background), redirecionamento de saídas e também sobre os códigos
de escape dos programas.
Execução em foreground e background
Quando executamos um programa, o shell fica esperando o mesmo terminar para depois nos
devolver a linha de comando. Por exemplo, quando executamos o comando cp arquivo1
arquivo2,o shell executa esse comando, fica esperando ele terminar, para depois nos retornar a
linha de comando. Isso chama-se execução em primeiro plano, ou foreground, em inglês.Agora
digamos que o arquivo a ser copiado seja muito grande, digamos, 50Mb. Enquanto o comando
cp é executado, vamos ficar com o shell preso a ele todo esse tempo, ou seja, cerca de 1 ou 2
minutos. Somente após isso vamos ter a linha de comando de volta para podermos continuar
trabalhando.
E se pudéssemos dizer ao shell para executar um programa e nos retornar a linha de comando
sem ficar esperando o tal programa terminar? Seria muito melhor, não? Em alguns casos seria.
E podemos fazer isso.
Uma maneira fácil é colocar o sinal de & depois de um comando. No exemplo acima ficaria:
neo@matrix:~$ cp arquivo1 arquivo2 &
[1] 206
neo@matrix:~$
Pronto, assim que teclarmos [enter], teremos a nossa linha de comando de volta e mais duas
informações: "[1] 206".
A primeira informação ([1]) chama-se job. Ela identifica os programas que estão sendo
executados em bg (background). Por exemplo, se executarmos mais um programa em bg
enquanto este "cp" está sendo executado, o novo programa recebe o job de número 2 ([2]) e
assim por diante.
A segunda informação (206) é o pid do programa, ou seja, o número de processo que o kernel
dá a esse programa.
Mas aí temos um pequeno problema. Digamos que você queira trazer o programa para fg, por
exemplo, se o programa executado em bg for um tocador de mp3 e você quiser mudar a
música. Como fazemos? Usamos o comando fg [job] (intuitivo, não ?) do bash. No exemplo
acima, digamos que eu execute o "cp" em bg, mas depois queira trazê-lo para fg para cancelá-
lo. Seria simples:
neo@matrix:~$ cp arquivo1 arquivo2 &
[1] 206
neo@matrix:~$ fg 1
cp arquivo1 arquivo2
Assim trazemos o "cp" para primeiro plano e a linha de comando só retorna quando ele
terminar.
Opcional: Uma outra maneira de colocar um programa para rodar em bg é utilizando um truque
do bash (não sei se esta opção está disponível em outros shells).Digamos que você execute o
comando "cp" e esqueça de colocar o sinal "&". E aí? Tem que ficar esperando acabar ou
cancelar o comando? Não, podemos teclar: Ctrl + Z.
Ao fazer isso, paramos a execução do programa. Então é só dar o comando bg [job] (intuitivo
também, né?):
neo@matrix:~$ cp arquivo1 arquivo2
* aqui teclamos Ctrl + Z *
[1]+ Stopped cp -i arquivo1 arquivo2
neo@matrix:~$ bg 1
[1]+ cp -i arquivo1 arquivo2 &
neo@matrix:~$
Quando teclamos o Ctrl + Z, o bash nos diz que o job 1 foi parado ([1]+ Stopped) e quando
executamos "bg 1" ele nos diz que o comando voltou a ser executado, mas em bg (repare o
sinal de "&" no final da linha): [1]+ cp -i arquivo1 arquivo2 &.
Redirecionamento de saídas
Muitos programas que executamos geram saídas no console, ou sejam, emitem mensagens para
os usuários. Por exemplo, queremos achar quantos arquivos no nosso sistema tem "netscape"
no nome:
neo@matrix:~$ find / -name netscape
/usr/lib/netscape
/usr/lib/netscape/netscape
/usr/lib/netscape/nethelp/netscape
/usr/local/bin/netscape
Agora se quisermos procurar quantos arquivos compactados com o gzip (extensão .gz) tem no
nosso sistema para depois analisá-los e possivelmente apagar os repetidos ou inúteis, teremos
uma lista muito grande. Aqui no meu sistema deu mais de 1000 arquivos. Então, seria útil
podermos enviar as mensagens que vão para o console, para um arquivo. Assim, poderíamos
analisá-lo depois de executar o comando. Isso é extremamente útil ao trabalharmos com shell
script - enviar as saídas dos comandos para arquivos para depois analisá-las. Exemplificando:
neo@matrix:~$ find / -name "*.gz" > lista.txt
find: /home/vera: Permissão negada
find: /home/pri: Permissão negada
find: /root: Permissão negada
neo@matrix:~$
Notamos que nem tudo foi para o arquivo lista.txt. As mensagens de erro foram para o console.
Isso porque existem dois tipos de saída: a saída padrão e a saída de erro.A saída padrão é a
saída normal dos programas, que no caso acima, seria os arquivos encontrados. E a saída de
erro, como o próprio nome diz, são os erro encontrados pelo programa durante sua execução,
que devem ser informados ao usuário, como os erros de "permissão negada".
E aí, como selecionar uma ou outra? É simples, apenas devemos indicar o "file descriptor" (fd)
delas. Não vamos entrar em detalhes sobre o que é "descritor de arquivos" por fugir do nosso
escopo e ser um pouco complicado, apenas temos que saber que o fd 1 corresponde a saída
padrão e o fd 2 a saída de erro. Assim, no exemplo acima, para enviar os erro para o arquivo
erros.txt e a saída padrão para o arquivo lista.txt, usaríamos:
neo@matrix:~$ find / -name "*.gz" 1> lista.txt 2> erros.txt
Ou seja, é só por o número da saída desejada antes do sinal de ">".
Agora digamos que queremos ver o conteúdo do arquivo lista.txt. Podemos abrí-lo com um
editor de textos ou usar o "cat". Optando pela última opção:
neo@matrix:~$ cat lista.txt
/home/neo/gkrellm-0.10.5.tar.gz
/home/neo/linuxcall-interface-beta.tar.gz
...
<<< mais de 1000 linhas
neo@matrix:~$
Temos um problema. O arquivo tem mais de 1000 linhas e não conseguimos vê-lo inteiro.
Podemos redirecionar a saída do comando "cat" para o comando "more", que dá pausa entre as
telas:
neo@matrix:~$ cat lista.txt | more
.........
Veja que utilizamos o caractere "|", chamado "pipe". Não poderíamos ter utilizado o sinal de
">"? Não, o sinal de ">" é somente para enviar a saída para um ARQUIVO. Para enviar a saída
de um comando para a entrada de outro, usamos o pipe.
As vezes queremos que além da saída ir para um arquivo, ela também vá para a tela. Temos um
programinha que faz isso. Ele chama-se "tee". Veja o exemplo a seguir:
neo@matrix:~$ find / -name "*.gz" 2> erros.txt | tee lista.txt
O que fizemos???Primeiro pegamos a saída de erro e enviamos para o arquivo erros.txt. O
restante, ou seja, a saída padrão, estamos enviando para a entrada do comando tee (usando o
pipe). O tee simplesmente pega o que ele recebe (através do pipe) e joga no arquivo lista.txt e
na tela. Assim, além de gravarmos a saída num arquivo, podemos mostrar ao usuário o que está
acontecendo. Isso é muito útil quando escrevemos alguns scripts.
Resumindo: aprendemos que podemos redirecionar a saída padrão ou de erro de programa para
um arquivo usando respectivamente "1>" ou "2>" ou também enviar a saída para a entrada de
outro programa usando o pipe "|".
Códigos de Escape
Toda vez que executamos um programa em Unix, ele retorna um código de escape ao finalizar.
Esse código reflete a condição em que o programa finalizou. Se ocorreu tudo certo e o programa
terminou normalmente, ele retorna 0. Se ocorreu algum problema, o programa retorna um
código diferente de 0, geralmente variando com o problema ocorrido.
Esse código de retorno é extremamente importante em shell script, pois é assim que testamos
se uma certa ação ocorreu bem ou teve problemas.Esse código é armazenado pelo bash numa
variável chamada "?" (isso mesmo, somente o sinal de interrogação ;-)).
Por exemplo, vamos executar um "ls" em um diretório que existe e ver o código de retorno:
neo@matrix:~$ ls /boot
System.map boot.0300 boot.b boot_message.txt chain.b config map
os2_d.b
neo@matrix:~$ echo $? 0
neo@matrix:~$
Ou seja, o "ls" foi executado normalmente, retornando 0. Agora vamos executá-lo num diretório
que não existe:
neo@matrix:~$ ls /diretorio_invalido
/bin/ls: /diretorio_invalido: Arquivo ou diretório não encontrado
neo@matrix:~$ echo $?
1
neo@matrix:~$
Como esperado, obtemos o retorno de erro 1.
Alguns programas tem muitos códigos de retorno. Por exemplo, os códigos de retorno do "pppd"
vão até o 19. Assim é possível saber porque ele foi finalizado. Se você colocar uma senha errada
no pppd e tentar conectar, ele vai terminar com o código 19.
man pppd
...
17 The PPP negotiation failed because serial loopback was detected.
18 The init script failed (returned a non-zero exit status).
19 We failed to authenticate ourselves to the peer.
...
Um detalhe importante: quando executamos um programa em background, ele sempre retorna
um código 0 para o shell, mesmo que durante sua execução ocorra algum problema. Assim,
quando executamos um programa em bg, perdemos essa facilidade de testar como foi seu
término.
neo@matrix:~$ ls /diretorio_invalido &
[1] 230
neo@matrix:~$ /bin/ls: /diretorio_invalido: Arquivo ou diretório não
encontrado
[1]+ Exit 1 /bin/ls $LS_OPTIONS /diretorio_invalido
neo@matrix:~$ echo $?
0
Como vemos, ao terminar, ele emite uma mensagem dizendo que finalizou com código 1 ([1]+
Exit 1) mas quando testamos a variável "?", o bash nos diz "0".
Conclusão
Como todos os programas tem que terminar com um código de retorno que tenha algum
significado, nossos shell scripts também terão que finalizar indicando o que aconteceu, se
ocorreu tudo bem ou se ouve erro. Mas isso discutiremos melhor mais pra frente.
O importante aqui é saber que todos os programas terminam com um código de retorno, os
quais usaremos nos nossos scripts para testar o término dos programas.
Curso de Shell - Aula III
Introdução
Nesta terceira parte do nosso curso de shell script, vamos tratar de "condicionais". Condicionais
são comandos que avaliam uma expressão. Se ela for verdadeira, uma determinada rotina é
executada. Caso contrário, outra rotina pode ser executada.
O famoso "if"
O bash nos oferece, entre outros, o comando IF (ele é um comando embutido no bash e não um
programa como o "ls", o "cp" etc.). A forma mais simples de representar uma condicional
utilizando o IF, é da seguinte forma básica:
if [condição];
then comandos1;
else comandos2;
fi;
Se [condição] for verdadeira, os comandos1 são executados. Se for falsa, os comandos2 são
executados.Mas para o IF, o que é uma condição verdadeira ou uma falsa?
Como foi explicado na aula anterior, TODO comando em Unix tem um código de retorno.
Geralmente o código "0" (zero) significa que o comando foi executado perfeitamente e terminou
bem. Códigos maiores que zero significam que alguma coisa de errado ocorreu.
É assim que o IF verifica uma condição. Se o seu código de retorno for zero, então ela é
considerada verdadeira. Caso contrario, ela é falsa.Mas então a [condição] tem que ser um
comando, certo? Exatamente. Vamos exemplificar:
neo@matrix:~$ if ls /boot;
then echo "O diretório existe.";
else echo "Diretório inválido.";
fi;
System.map boot.0300 boot.b boot_message.txt chain.b config map
os2_d.b
O diretório existe.
O que fizemos? Logo após o if, nós colocamos um comando: "ls /boot". O que o IF faz? Ele
executa esse comando (por isso que temos a segunda linha começada por "System.map", que é
o conteúdo do meu diretório /boot) e avalia o seu código de saída. Como o "ls" foi executado
corretamente, ele retorna zero, significando verdadeiro para o IF, que executa o comando logo
após o "then", ou seja, o echo "O diretório existe.", mostrando essa mensagem no console.
Agora vamos colocar um diretório que não existe:
neo@matrix:~$ if ls /dir_invalido;
then echo "O diretório existe.";
else echo "Diretório inválido.";
fi;
/bin/ls: /dir_invalido: Arquivo ou diretório não encontrado
Diretório inválido.
A lógica é a mesma. Executa o "ls /dir_invalido", que retorna um código maior que zero. O IF
avalia como falso e executa o comando após o else: echo "Diretório inválido".
Nós poderíamos omitir a segunda linha dos dois exemplo (a que mostra o conteúdo de /boot no
primeiro exemplo e a mensagem de erro emitida pelo ls dizendo que /dir_invalido não existe no
segundo), apenas redirecionando as saídas para /dev/null, ou seja:
neo@matrix:~$ ls /boot 1> /dev/null 2> /dev/null
Nota: Tem um macete que possui o mesmo efeito. Em vez de colocar: "1> /dev/null 2>
/dev/null" podemos colocar "2&>1", que é menor e mais simples.
O comando "test"
Bom, aprendemos que o IF avalia a código de retorno de um comando. Mas muitas vezes, para
não dizer a maioria, nós queremos avaliar "expressões", ou seja, verificar se uma variável é
igual a outra, se ela esta vazia etc.
Para isso, nós temos outro comando chamado "test" (intuitivo o nome, não?). Ele funciona da
seguinte maneira: test [expressão].
O test pode testar operações de três tipos: strings, arquivos e aritméticas.
Expressões usando strings:
O test pode apenas comparar strings, ou seja, verificar se uma é igual a outra, e verificar se
uma string é vazia ou não. Vamos aos exemplos para facilitar o entendimento:
neo@matrix:~$ test "a" = "a"
neo@matrix:~$ echo $?
0
neo@matrix:~$ test "a" = "b"
neo@matrix:~$ echo $?
1
neo@matrix:~$ test "a" != "b"
neo@matrix:~$ echo $?
0
Aqui comparamos a string "a" com "b". Como era de se esperar, o primeiro retornou verdadeiro
(zero), pois a = a e o segundo retornou falso. No terceiro, o símbolo "!=" significa "diferente".
neo@matrix:~$ test -z "neo"
neo@matrix:~$ echo $?
1
neo@matrix:~$ test -z ""
neo@matrix:~$ echo $?
0
neo@matrix:~$ test -n "neo"
neo@matrix:~$ echo $?
0
neo@matrix:~$ test -n ""
neo@matrix:~$ echo $?
1
Acima temos os testes de vazio. A opção "-z" verifica se é vazio, e "-n" se não é vazio. No
primeiro caso, ele testa se "neo" é uma string vazia, retornando falso. Já no segundo caso, como
"" é vazia, retorna verdadeiro. O terceiro e quarto são semelhantes aos primeiros, mas com "-
n".
Expressões com arquivos:
Os testes que podem ser feitos com arquivos são para verificar determinadas caracteristicas,
como se ele existe, se é executavel, se é um link simbólico, se é um diretório etc.
Alguns exemplos:
A opção "-e" verifica apenas se um arquivo existe e a opção "-d" verifica se o arquivo é um
diretório.
A opção "-nt" verifica se o primeiro arquivo é mais novo que o segundo (nt = newer than) e "-
ot" verifica se o primeiro é mais velho que o segundo (od = older than):
neo@matrix:~$ test -e /vmlinuz
neo@matrix:~$ echo $?
0
neo@matrix:~$ test -d /vmlinuz
neo@matrix:~$ echo $?
1
neo@matrix:~$ test -e /usr
neo@matrix:~$ echo $?
0
neo@matrix:~$ test -d /usr
neo@matrix:~$ echo $?
0
neo@matrix:~$ test /usr -nt /vmlinuz
neo@matrix:~$ echo $?
0
neo@matrix:~$ test /usr -ot /vmlinuz
neo@matrix:~$ echo $?
1
A seguir, temos uma lista de várias opções disponíveis:
-b arquivo - Verdadeiro se arquivo é um arquivo de bloco, como /dev/hda.
-c arquivo - Verdadeiro se arquivo é um arquivo de caracter, como /dev/tty1.
-d arquivo - Verdadeiro se arquivo é um diretório.
-e arquivo - Verdadeiro se arquivo existe.
-f arquivo - Verdadeiro se arquivo existe e é um arquivo comum.
-s arquivo - Verdadeiro se arquivo existe e não é vazio.
-h arquivo - Verdadeiro se arquivo é um link simbólico.
-p arquivo - Verdadeiro se arquivo é um "named pipe" (fifo, lifo, etc).
-S arquivo - Verdadeiro se arquivo é um "socket".
-k arquivo - Verdadeiro se arquivo tem seu "sticky bit" ligado.
-r arquivo - Verdadeiro se arquivo pode ser lido pelo usuário atual.
-w arquivo - Verdadeiro se arquivo pode ser escrito pelo usuário atual.
-x arquivo - Verdadeiro se arquivo pode ser executado pelo usuário atual.
-O arquivo - Verdadeiro se arquivo pertence ao usuário atual.
-G arquivo - Verdadeiro se arquivo pertence ao grupo do usuário atual.
-N arquivo - Verdadeiro se arquivo foi modificado desde a ultima vez que foi
lido.
Expressões Aritméticas
Expressões aritméticas consistem com comparar dois números, verificando se são iguais, ou se o
primeiro é maior que o segundo etc.
Infelizmente não podemos apenas utilizar os símbolos conhecidos para igual (=), maior que (>),
menor que (<) etc. Temos que usar operadores reconhecidos pelo "test". Assim, não podemos
fazer: "test 1 = 1", devemos utilizar o operador "-eq" (equal): "test 1 -eq 1". A seguir, temos
uma lista dos operadores:
-eq (equal): Igual;
-ne (not-equal): Não Igual (diferente);
-lt (less than): Menor que (<);
-le (less than or equal): Menor ou igual ( <= );
-gt (greater than): Maior que (>);
-ge (greater than or equal): Maior ou igual (>=);
Alguns exemplos:
neo@matrix:~$ test 1 -lt 2
neo@matrix:~$ echo $?
0
neo@matrix:~$ test 1 -gt 2
neo@matrix:~$ echo $?
1
neo@matrix:~$ test 2 -gt 1
neo@matrix:~$ echo $?
0
neo@matrix:~$ test 2 -ge 2
neo@matrix:~$ echo $?
0
Para finalizar, vamos fazer duas considerações. A primeira é de que o comando "test" pode ser
substituido por um par de colchetes [ ]. Assim, o comando test "a" = "b" pode ser escrito como
[ "a" = "b" ].
Essa segunda nomenclatura fica mais fácil e simples, principalmente quando estamos utilizando
IF:
if [ -e /vmlinuz ]; é mais intuitivo e simples que if test -e /vmlinuz;.
A segunda consideração é que, obviamente, podemos utilizar variáveis no lugar dos argumentos
(caso contrário, ficaria difícil utilizar comandos de condicionais em shell script). Assim, se
tivermos duas variaveis, valor1=5 e valor2=8:
[ "$valor1" = "$valor2" ] , [ "$valor1" -lt "$valor2" ] etc.
É importante colocarmos os valores entre aspas duplas ("), pois assim o bash pode substituir o
que se encontra dentro dessas aspas. Se colocarmos entre aspas simples ('), impedimos o bash
de alterar o que se encontra dentro delas. Se não utilizarmos as aspas duplas, vamos ter
problemas, principalmente ao trabalharmos com string.
Por exemplo, queremos comparar dois nomes, que se encontram em duas
variaveis:nome1="fulano de tal" e nome2="ciclano".Montando nossa expressão condicional:
[ "$nome1" = "$nome2" ].O bash irá expandir isso para: [ "fulano de tal" = "ciclano" ], ficando
claramente definidos o primeiro e o segundo argumento.
Agora, se não usarmos aspas: [ $nome1 = $nome2 ]. O bash irá expandir isso para: [ fulano de
tal = ciclano ]. Perceba que os argumentos se misturam e o bash não vai saber o que
comparar.Por isso é importante colocarmos os argumentos entre aspas duplas.
Conclusão
Resumindo, aprendemos na aula de hoje como utilizar comandos condicionais. Isso será
fundamental nas proximas aulas, onde iremos tratar os comandos de laço, como o while. Não
perca!
Curso de Shell - Aula IV
Introdução
Nesta aula vamos aprender sobre comandos de laço como o while, for, case e select. Eles nos
permitem executar alguns comandos diversas vezes, sob determinadas condições e até montar
menuzinhos para interagir com o usuário.
While
Este é provavelmente o comando de laço mais utilizado em programação. Seu entendimento é
simples. Ele testa uma condição (como faz o IF) e executa um conjunto de comandos se esta
condição for verdadeira. Após a execução desses comandos, ele torna a testar a condição e se
esta for verdadeira, ele reexecuta os comandos e assim por diante.
Sua sintaxe é a seguinte:
while [ condição ];
do
comando 1;
comando 2;
...
done;
O parâmetro [ condição ] funciona exatamente igual ao do IF. Não voltarei a abortar os
parâmetros condicionais pois eles já foram explicados na aula 3. Em caso de dúvida sobre isso,
uma rápida revisão na aula 3 é suficiente.
Bom, vamos ao exemplo mais simples do While: um contador.
x = 0
While [ "$x" -le 10 ];
do
echo "Execução número: $x"?;
x = $((x+1));
done;
Analisando:
Na primeira linha temos a condição: enquanto o valor da variável x ( $x ) for menor-igual ( -le )
a 10, faça: mostre "Execução número: " e o valor de x ($x). Faça x = x + 1. Isso no bash é feito
pelo comando $(( )). Ele realiza operações algébricas com variáveis. No caso acima, estamos
somando x + 1 e colocando o resultado no próprio x.
Preste atenção, que as linhas do While precisam de um ";" para terminar, exceto a que contém o
"do", pois ele representa o começo do bloco de comandos.
Quando executamos o script acima, temos uma contagem de 1 até 10:
neo@matrix:~$ x=0;
while [ "$x" -lt 10 ];
do x=$((x+1));
echo "Execução número: $x";
done;
Execução número: 1
Execução número: 2
...
Execução número: 10
neo@matrix:~$
O While tem muita utilidade em programação, mas fica difícil dar exemplos usando somente ele,
pois geralmente ele está associado a execução de outros programas e rotinas mais complexas.
Eu costumo usar ele, por exemplo, quando quero que o napster fique tentando conectar, pois
quando ele vai tentar conectar o servidor e não consegue, ele simplesmente termina. Ai eu
coloco o while testando a código de retorno dele (lembram da variável $? ) e enquanto estiver
diferente de zero (o napster terminou com erro), ele fica executando o napster:
? = 1; while [ "$?" -ne "0" ]; do ./nap; done;
O comando "? = 1" tenta atribuir 1 a variável ?. Isso provoca um erro, pois a variável ? É
somente de leitura. Isso é necessário para que ? Contenha algo diferente de 0, pois senão o
While não executa a primeira interação.
For
O for é semelhante ao while usado como um contador. É necessário fornecer uma lista de nomes
e ele executa os comandos para cada nome na lista. Parece meio confuso, mas é simples. Veja a
sintaxe:
for <var> in <lista>;
do
comandos
done;
O For associa o primeiro item da lista de nomes à variável <var> e executa os comandos. Em
seguida, associa novamente o segundo item da lista à <var> e executa novamente os
comandos... e assim por diante, até acabar a lista.
Veja o exemplo:
neo@matrix:~$
for x in Compra Venda Aluguel;
do echo $x;
done;
Compra
Venda
Aluguel
Ou seja, primeiro ele coloca "Compra" na variável x e executa os comandos, no caso, "echo $x",
e assim por diante.
Podemos facilmente implementar um contador, usando em conjunto com o for, o programinha
"seq". Ele simplesmente gera uma seqüência de números. Por exemplo, "seq 10" gera uma
seqüência de 1 até 10. Assim, podemos usá-lo no for:
for x in $(seq 10);
do echo $x;
done;
Esse comando é semelhante ao contador implementado com o While. Primeiro o x vale 1 e o for
executa os comandos. Depois x vale 2 e ele reexecuta os comandos...
Vamos usar o For para renomear os arquivo de um diretório, mudando todos os arquivo
terminados em ".mp3" para ".mp3.bak".
for x in *; do
mv "$x" "${x}.bak";
done;
for x in *.mp3; do
if [ -e "$x" ];
then mv "$x" "${x}.bak";
fi;
done;
No local de <lista> nos colocamos "*.mp3". Isso diz ao bash para expandir (transformar) ele na
lista de arquivos terminados com ".mp3". Senão houver nenhum arquivo com essa terminação,
o bash não faz nada, ficando para o for a string "*.mp3". Por isso precisamos do IF para testar
se o arquivo existe.
Experimente no seu sistema.
echo *.mp3
Vai mostrar os arquivos no diretório atual com terminação mp3, mas sem quebra de linha entre
eles, ou seja, um nome após o outro. Se não houver nenhum arquivo com terminação mp3, ele
apenas vai mostrar "*.mp3".
Bom, voltando ao For, ele vai atribuir a "x" cada nome na lista de arquivos com terminação
".mp3" e executar os comandos seguintes.
Primeiro ele testa para ver se o arquivo existe ( if [ -e "$x" ]; ), e se existir, renomeia ele para o
seu próprio nome acrescido de ".bak" ( ${x}.bak ).
Resumindo, o For faz isso: você fornece uma lista de nomes para ele e ele vai atribuindo esses
nomes, em ordem e um por vez, à variável <var> e executa os comandos entre o "do" e o
"done;".
Case
O Case está mais para um comando condicional do que para comando de laço, visto que ele não
executa "loopings" como o While e o For.
Ele geralmente é utilizado como substituição de vários IFs.. Um exemplo clássico e muito
utilizado é quando você precisa testar um parâmetro fornecido na linha de comando. O Case é
utilizado desta forma em scripts de inicialização de serviços do sistema.
Vou mostrar a sintaxe em em seguida um script que inicialize/ reinicialize ou pare algum serviço
(como o sendmail, apache, bind, etc).
Sintaxe:
case <parâmetro> in
<opção 1>)
<comandos 1> ;;
[opção 2])
<comandos 2> ;;
* )
<comandos se não for nenhuma das opções> ;;
esac
Vamos as explicações. O Case pega a string fornecida em <parâmetro> e compara com <opção
1>. Se forem iguais, ele executa <comandos 1> e sai fora. Caso contrario, ele compara
<parâmetro> com <opção 2> e assim por diante.
Caso <parâmetro> não seja igual a nenhuma das opções, ele executa os comandos da opção
"*", se este existir.
Prestem atenção a alguns detalhes na sintaxe. Deve existir um ")" após cada opção e também
um ";;" após todos os comandos de cada opção. Vejam o exemplo abaixo:
case "$1" in
'start' )
echo "Iniciando o serviço..."
<comandos para iniciar o serviço> ;;
'restart' )
echo "Reinicializando o serviço..."
<comandos para reinicializar o serviço> ;;
'stop' )
echo "Parando o serviço..."
<comandos para parar o serviço> ;;
*)
echo "Opção invalida!"
echo "As opções válidas são:
start, stop e restart"
;;
esac
O Case serve exatamente para isso, ou seja, evitar o teste de vários Ifs. No caso acima,
teríamos que utilizar 3 Ifs. Mesmo se o primeiro já fosse verdadeiro, o bash iria testar o segundo
e o terceiro, ou seja, ia perder tempo desnecessariamente. Já no case isso não acontece. Após
entrar em uma opção e executar seus comandos, ele já pula fora do case sem testar as outras
opções abaixo.
Select
O Select é um comando de laço que nos permite mostrar um pequeno menuzinho de opções
para o usuário. Cada opção possui um número e para escolher, o usuário digita o número
correspondente a opção desejada. Vejamos a sintaxe a seguir:
select <var> in <lista de opções>;
do
<comandos>
done;
Como disse acima, o select vai mostrar as opções contidas em <lista de opções>, uma por linha,
com um número na frente e espera que o usuário digite a opção desejada. Ao digitar a opção, o
select atribui o nome da opção a variável <var> e executa os comandos. Para sair do select, é
necessário executar o comando "break". Vamos a um exemplo:
select x in Iniciar Reiniciar Parar Sair; do
echo "Opção Escolhida: $x"
if [ "$x" == "Sair" ]; then break; fi;
done;
Ou seja, se o usuário escolher alguma opção diferente de "Sair", o script apenas escreve a
opção. Se for escolhida Sair, ele mostra a opção, entra no IF e executa o break, saindo do
select.
É interessante combinar o Select com o Case. Vamos mostrar como ficaria aquele exemplo do
case, de iniciar um serviço, utilizando o Select, para tornar o script interativo:
select x in Iniciar Reiniciar Parar Sair; do
case "$x" in
'Iniciar' )
echo "Iniciando o serviço..." ;;
'Reiniciar' ) echo "Reinicializando o serviço..." ;;
'Parar' ) echo "Parando o serviço..." ;;
'Sair' ) echo "Script encerrado." break
;;
*) echo "Opção inválida!" ;; esac
done;
Primeiramente o Select mostra um menuzinho:
1) Iniciar
2) Reiniciar
3) Parar
4) Sair
#?
Quando o usuário digitar um número de opção, o select executa o case e este compara a
variável x com suas opções. Se achar alguma, executa seus comandos, no caso um echo. Se o
usuário escolher Sair, além do echo, ele executa o "break", que interrompe o select:
neo@matrix:~/test$ ./t
1) Iniciar
2) Reiniciar
3) Parar
4) Sair
#? 1
Iniciando o serviço...
1) Iniciar
2) Reiniciar
3) Parar
4) Sair
#? 5
Opção inválida!
1) Iniciar
2) Reiniciar
3) Parar
4) Sair
#? 4
Script encerrado.
neo@matrix:~/test$
Bom pessoal, acho que por hoje é só. ;-) Espero que vocês tenham pego a idéia de como
funciona comandos de laços. Pelos menos sabendo a utilidade, sintaxe e como funcionam,
quando surgir a necessidade, vocês já vão saber quais ferramentas usar.
Qualquer dúvida, sugestão, etc, podem me enviar um e-mail. Terei o maior prazer em
responder. Até a próxima aula!
Curso de Shell - Aula V
Introdução
Nesta aula teremos um breve tutorial sobre o Grep. Ele não é somente um dos comandos mais
úteis, mas o seu domínio abre portas para dominar outros poderosos comandos, como o sed
(que trataremos na próxima aula), awk, perl, etc.
Eu fiz uma adaptação/modificação de um tutorial que eu tenho, e por sinal é excelente, sobre o
Grep e Expressões Regulares em inglês. Espero que tenha ficado legal e vocês gostem.
O que ele faz?
O grep basicamente faz buscas. Mais precisamente:
grep <palavra> <file>
Retorna todas as linhas do arquivo <file> que contenham <palavra>
Outro jeito de usar o grep é atraves de pipe (lembram dos pipes?). Por exemplo:
ls | grep <palavra>
Lista todos os arquivos que contenham <palavra> em seu nome. Ou seja, a entrada do grep é
uma lista de arquivos (gerada pelo ls) que será filtrada, sendo impressas somente as linhas que
contenham <palavra>.
Usando caracteres coringas
Suponho que todos saibam o que são caracteres coringas. Caso contrário, coringas são
caracteres especiais que substituem outros. Geralmente o caracter "*" é um coringa que
significa "qualquer caracter em qualquer quantidade". Por isso se a gente executar "ls *", onde
"*" entra no lugar do "nome do arquivo", significando qualquer string de qualquer tamanho. Por
isso ele lista todos os arquivos.
Mas agora voltemos ao grep. Será que ele aceita coringas ??? A resposta é mais do que sim. O
grep suporta algo que vai além de coringas, ele suporta Expressões Regulares. Mas vamos
começar apenas com coringas. Um dos mais usados com o grep é o "." Vamos a um exemplo:
>cat file
file
big
bad bug
bigger
boogy
>grep b.g
big
bad bug
bigger
Note que boogy não casa, desde que "." significa "qualquer e apenas um caracter". Para
significar strings arbitrárias utilizamos "*", que funciona da seguinte maneira:
"A expressão consistindo de um caracter seguido por um * casa com qualquer número (inclusive
zero) de repetições desse caracter. Em particular, ".*" significa qualquer string."
Para compreendermos vamos a mais exemplos:
>cat file
big
bad bug
bag
bigger
boogy
>grep b.*g file
big
bad bug
bag
bigger
boogy
>grep b.*g. file
bigger
boogy
>grep ggg* file
bigger
Avançando para expressões regulares
Os coringas são o começo, mas a idéia vai mais longe. Por exemplo, suponha que queremos
uma expressão que case com Frederic Smith ou Fred Smith, ou seja, a string "eric" é opcional.
Primeiro, introduzimos o conceito de um "caracter escapado (escaped character)".
"Um caracter escapado é um caracter precedido por uma barra invertida (  ). Essa barra
invertida faz o seguinte: (a) Remove qualquer significado especial do caracter. (b) acrescenta
um significado especial a um caracter que não tenha um significado especial."
Parece complicado, mas veja nos exemplo que é um tanto quanto simples:
Para procurar uma linha contento o texto "hello.gif", o comando correto seria:
grep 'hello.gif' file
Desde que "grep 'hello.gif' file" iria resultar linhas contendo: hello-gif , hello1gif , helloagif , etc.
Ou seja, a barra invertida remove o significado especial do ".", passando esse a significar um
simples ponto ao invés de um coringa.
Agora vamos passar para expressões agrupadas, a fim de encontrar um jeito de criar uma
expressão que case com Frederic ou Fred. Primeiro vamos começar com o operador "?":
"Uma expressão consistindo de caracter seguido por uma interrogação escapada ( ? ) casa com
zero ou uma instância daquele caracter".
Exemplo:
"bugg?y" casa com o seguinte: bugy , buggy mas não com bugggy
neo@matrix:~$ echo bugy | grep "bugg?y"
bugy
neo@matrix:~$ echo bugggy | grep "bugg?y"
neo@matrix:~$
Agora vamos para expressões agrupadas. No nosso exemplo, queremos tornar opcional a string
"eric" após "Fred", ou seja, não apenas um caracter mas sim um conjunto de caracteres (string).
"Uma expressão dentro de parênteses escapados é tratada como um único caracter"
Exemplos:
"Fred(eric)?" Smith casa com "Fred Smith" or "Frederic Smith" (abc)* casa com abc ,
abcabcabc, etc (isto é, qualquer número de repetições da string "abc", incluindo zero).
Note que temos que tomar cuidado quando nossas expressões contém espaços em branco.
Quando eles aparecem, precisamos colocar a expressão entre aspas, para que o shell não
interprete mal nosso comando. Para o exemplo acima:
grep "Fred(eric)? Smith" file
Eu aconselho fortemente a sempre usar aspas, mesmo que não usemos espaços em brancos. Já
tive muita dor de cabeça porque expressões e comandos não funcionavam simplesmente por
não estarem entre aspas. Um dos exemplo acima (o do bugg?y) não funciona no meu sistema
se não estiver entre aspas. Veja:
neo@matrix:~$ echo bugy | grep "bugg?y"
bugy
neo@matrix:~$ echo bugy | grep bugg?y
neo@matrix:~$
Outros operadores úteis
Para casar algum caracter de uma lista, use [ ] Veja:
"[Hh]ello" casa com linhas contendo "hello" ou "Hello"
Faixas de caracteres também são permitidos:
[0-3] é o mesmo que [0123]
[a-k] é o mesmo que [abcdefghijk]
[A-C] é o mesmo que [ABC]
[A-Ca-k] é o mesmo que [ABCabcdefghijk]
Existem também algumas formas alternativas:
[[:alpha:]] é o mesmo que [a-zA-Z]
[[:upper:]] é o mesmo que [A-Z]
[[:lower:]] é o mesmo que [a-z]
[[:digit:]] é o mesmo que [0-9]
[[:alnum:]] é o mesmo que [0-9a-zA-Z]
[[:space:]] casa com qualquer quantidade de espaços, inclusive
tabulações
Essas formas alternativas, como [[:digit:]] é preferível ao método direto, [0-9].
Os [ ] podem ser usado para indicar caracteres que NÃO devem estar na expressão. É só colocar
o sinal ^ na primeira posição da lista. Veja:
neo@matrix:~$ echo hello | grep "[Hh]ello"
hello
neo@matrix:~$ echo hello | grep "[^Hh]ello"
neo@matrix
Outro exemplo, um pouco mais complicado:
grep "([^()]*)a" file
(hello)a
(aksjdhaksj d ka)a
Retorna qualquer linha contendo um par de parentes seguido por "a" e que NÃO contenham
outros parênteses dentro.
Mas não com:
x=(y+2(x+1))a
Casando com um número especifico de repetições
Suponha que você queira casar um número específico de repetições de uma expressão. Um bom
exemplo são números de telefones. Você pode procurar por um número de telefone com sete
dígitos, assim:
grep "[:digit:]{3}[ -]?[:digit:]{4}" file
Ou seja, três dígitos, opcionalmente um espaço ou um hífen e mais 4 dígitos.
Procurando por começo e fim de linha: Isso é muito interessante. Digamos que você queira
procurar por linhas que contendo espaços em brancos no começo da linha, a palavra hello e
então o fim da linha. Vamos começar com este exemplo:
>cat file
hello
hello world
hhello
>grep hello file
hello
hello world
hhello
Isso não é o que nós queremos. O que está errado ? O problema é que o grep procura por linhas
contendo a string hello e todas as linhas especificadas contem ela. Para contornar isso,
introduzimos os caracteres de começo e fim de linha:
"O caracter ^ significa começo de linha e o $ significa fim da linha"
Retornando ao nosso exemplo:
grep "^[[:space:]]*hello[[:space:]]*$" file
Ou seja, o começo da linha, qualquer quantidade de espaço em branco (inclusive zero), a
palavra hello, qualquer quantidade de espaço em branco e o fim da linha. Essa expressão faz o
que a gente quer, retornando somente a linha que contém a palavra hello. Outro exemplo:
grep "^From.*Alex" /var/spool/mail/neo
Procura no meu inbox por mensagens de uma pessoa em particular (no caso, Alex). Esse tipo de
expressão regular é extremamente útil e filtros de e-mail, como o procmail, utilizam isso para
fazerem tudo.
Isso ou Aquilo: Procurando uma coisa OU outra:
"A expressão consistindo de duas expressões separadas pelo operador OU | casa linhas
contendo uma das duas expressões"
Note que você DEVE colocar a expressão dentro de aspas simples ou duplas:
grep "cat|dog" file casa com linhas contendo a palavra "cat" ou a
palavra "dog"
grep "I am a (cat|dog)" casa com linhas contendo a string "I am a
cat" ou a string "I am a dog".
Usando backreference (referencia anterior)
Digamos que você queira procurar strings que contenham uma substring em mais de um lugar.
Um exemplo é as tags de cabeçalhos de HTML. Suponha que eu queira procurar por
"<H1>alguma string</H1>". Isto é fácil de se fazer. Mas suponha que eu queira fazer o mesmo,
mas permita H2 H3 H4 H5 e H6 no lugar de H1. A expressão .* não é boa, desde que casa com
"<H1>alguma string</H3>" e nos queremos que a tag de abertura seja igual a de fechamento.
Para fazermos isso, usamos backreference:
"A expressão n onde n é um número, casa com o conteúdo do n-ésimo conjunto de parênteses
na expressão".
Nossa... isso realmente precisa de um exemplo!!!!
.* faz o que nos queríamos fazer acima...
"O Senhor (dog|cat) e a senhora 1 foram visitar o Senhor (dog|
cat) e a senhora 2"
Esse é outro exemplo bobo. Os casais tem sempre que serem iguais. Ou um casal de cachorro
ou de gato.
Alguns detalhes cruciais: caracteres especiais e aspas
Caracteres Especiais: Aqui nós descrevemos os caracteres especiais para RegExp (expressões
regulares) no grep. Note que no "egrep", que usa expressões regulares estendidas (atualmente
não tem nenhuma funcionalidade a mais que as expressões regulares normais do GNU grep), a
lista de caracteres especiais são os mesmos, diferindo somente que alguns não precisar estar
"escapados".
Os seguintes caracteres são considerados especiais, e precisam estar escapados:
?  . [ ] ^ $
Note que o sinal de $ perde seu sentido se tiver caracteres depois dele, do mesmo jeito que o
sinal ^ perde seu sentido se tiver caracteres antes dele. Os colchetes [ ] comportam-se um
pouco diferente. A baixo segue as regras para eles:
- O colchete direito ( ] ) perde seu sentido especial se colocado no começo de uma lista, por
exemplo: "[]12]" casa com ] , 1, or 2.
- Um hífen perde seu significado especial se colocado por último. Assim, [15-] casa com 1, 5 ou
-
- O caracter ^ perde seu sentido se não for colocado em primeiro lugar.
- A maioria dos caracteres especiais perdem seu significado especial se forem colocados dentro
de colchetes.
Aspas: Em primeiro lugar, aspas simples são mais seguras de usar porque elas protegem suas
expressões regulares de serem alteradas pelo bash (como foi visto nas aulas anteriores). Por
exemplo, grep "!" file vai produzir um erro, já que o shell pensa que "!" está se referindo ao
comando de histórico do shell, enquanto grep '!' file funciona perfeitamente.
Quando você deve usar aspas simples ? A resposta é: se você precisa usar variáveis do shell,
use aspas duplas. Caso contrário, use aspas simples. Por exemplo:
grep "$HOME" file
Procura em file pelo nome do seu diretório pessoal, enquanto grep '$HOME' file procura pela
string $HOME.
Sintaxe das expressões regulares estendidas
Agora vamos ver a sintaxe do egrep em contraste com a sintaxe do grep. Ironicamente, apesar
do nome "estendido", o egrep atualmente tem menos funcionalidade do que quando foi criado,
para manter a compatibilidade com o tradicional grep. A melhor maneira de fazer um grep
estendido é utilizar grep -E que usa a sintaxe de expressões regulares estendidas sem perda de
funcionalidade.
Bom, espero que vocês tenham tido uma boa idéia de como funcionam as expressões regulares.
Elas são extremamente importante, principalmente para utilizar o grep e o poderosíssimo sed,
do qual trataremos na próxima aula. Não se preocupem se estiverem confuso com as
expressões, quando começarem a utilizá-las, as idéias vão clareando. Até a próxima.
Curso de Shell - Aula VI
Introdução
Nesta aula continuaremos nosso tutorial, desta vez falando sobre o Sed. Vale lembrar que este
tutorial dará uma breve introdução ao Sed, ajudando os iniciantes a entender como ele funciona.
Portanto muitos comandos mais complexos serão omitidos, já que seria necessário um livro
inteiro para ensinar tudo sobre o Sed. Mas não se preocupem, ensinaremos o suficiente sobre
ele para utilização em shell script.
Resumo de RegExp
Vamos a um resumo sobre as expressões regulares, explicadas na aula anterior e agora
aplicadas ao Sed:
^ casa com o começo de linha
$ casa com o fim de linha
. casa com qualquer caracter simples (apenas um)
(caracter)* casa com qualquer ocorrência, em qualquer quantidade, de
(caracter)
(caracter)? casa com zero ou uma ocorrência de (caracter)
[abcdef] casa com qualquer caracter dentro dos [ ] (neste caso, a b c d e
ou f), faixas de caracteres como [a-z] são permitidas.
[^abcdef] casa com qualquer caracter NÃO incluído em [] (neste caso,
qualquer caracter que não seja a b c d e ou f)
(caracter){m,n} casa com m-n repetições de (caracter)
(caracter){m,} casa com m ou mais repetições de (caracter)
(caracter){,n} casa com n ou menos (também zero) repetições de
(caracter)
(caracter){n} casa com exatamente n repetições de (caracter)
(expressão) operador de grupo. n backreference - casa com o n-
ésimo grupo
expressão1|expressão2 casa com expressão1 ou expressão2. Funciona
com o GNU sed, mas essa característica pode não funcionar com outros
Seds.
Caracteres Especiais
Os caracteres especiais no Sed são os mesmo do Grep, com uma diferença: a barra normal / é
um caracter especial no sed. A razão disso ficará clara mais para frente quando estudarmos os
comandos do sed.
Como funciona: Uma breve introdução
O Sed funciona assim: ele lê da entrada padrão, uma linha de cada vez. Para cada linha, ele
executa uma série de comandos de edição e então a linha é escrita na saída padrão. Um
exemplo que mostra como ele funciona: Nós usamos o comando "s", que significa "substitute"
(substituir) ou "search and replace" (procurar e trocar). O formato é:
s/expressão-regular/texto-substituto/{flags}
Nós não vamos discutir todas as flags ainda. A única que usamos abaixo é a "g", que significa
"substitua todas as ocorrências":
>cat file
Eu tenho três cachorros e dois gatos
>sed -e 's/cachorros/gatos/g' -e 's/gatos/elefantes/g' file
Eu tenho três elefantes e dois elefantes
OK, então o que aconteceu? Primeiro o sed leu a linha do arquivo "file" e executou:
s/cachorros/gatos/g
que produziu o seguinte texto:
Eu tenho três gatos e dois gatos
e então o segundo comando foi executado na linha já editada e resultou:
Eu tenho três elefantes e dois elefantes
Nós atualmente damos um nome para o texto (geralmente uma linha) que o sed leu e está
processando (editando): ele chama-se "pattern space" (uma boa tradução seria "área de
edição").
O sed lê da entrada padrão e joga na sua área de edição, executando nela uma seqüência de
comandos de edição e então ele escreve o resultado na saída padrão.
Comandos de Substituição e Deleção
Primeiro, as maneiras mais usuais do sed é a seguinte:
>sed -e 'comando1' -e 'comando2' -e 'comando3' arquivo
>{comando shell} | sed -e 'comando1' -e 'comando2'
>sed -f sedscript.sed arquivo
>{comando shell} | sed -f sedscript.sed
Então, o sed pode ler do arquivo ou da entrada padrão, e os comandos podem ser especificados
em um arquivo de script ou na linha de comando. Esse arquivo, chamado sedscript.sed é um
arquivo que contém todos os comandos do sed, ao invés de serem especificados na linha de
comando. Esses sed's scripts são úteis quando precisamos de um processamento de texto mais
complexo e refinado.
Note o seguinte: se os comandos são lidos de um arquivo (sed script), espaços em branco
podem ser fatais. Eles podem fazer o script falhar sem explicação aparente. Eu recomendo editar
os arquivos de comandos do sed com um editor como o VIM que pode mostrar o final da linha e
você pode ver se existem espaços em branco entre os comandos e o fim da linha.
Comando de Substituição
O formato para o comando de substituição é o seguinte:
[endereço1[,endereço2]]s/procura/substituto/[flags]
As flags podem ser as seguintes:
n - troca a n-ésima ocorrência (na linha) do texto "procura" por
"substituto"
g - troca todas as ocorrências (na linha) do texto "procura" por
"substituto"
p - imprime a "área de edição" para a saída padrão se ocorrer uma
substituição com sucesso
w arquivo - imprime a "área de edição" para arquivo se ocorrer uma
substituição com sucesso
Se nenhuma flag for especificada, somente a primeira ocorrências na linha é substituída. Note
que nós quase sempre usamos o comando "s" ou com a flag "g" ou sem nenhuma flag.
Se um endereço é dado, então a substituição é aplicada a linhas que contenham aquele
endereço. Um endereço pode ser ou uma expressão regular dentro de barras normais /regexp/ ,
ou um número de linha. O símbolo $ pode ser usado no lugar do número da linha para denotar a
última linha.
Se dois endereços são fornecidos, separados por uma vírgula, então a substituição é aplicada a
todas as linhas entre duas linhas que casam com os endereços fornecidos.
Isto requer algum esclarecimento. Mais precisamente, a substituição ocorre em todas as linhas
desde a primeira ocorrência de "endereço1" até a primeira ocorrência de "endereço2".
Não se preocupe se isso tudo parece meio confuso. Os exemplos vão esclarecer melhor.
O comando de Deleção
A sintaxe desse comando é muito simples. Ai vai:
[endereço1[,endereço2]]d
Isto deleta o conteúdo da "área de edição" (se esta casar com os endereços fornecidos). Todos
os comandos seguintes serão pulados (já que não a nada a fazer com uma área de edição em
branco) e uma nova linha será lida e jogada na área de edição e todo o processo se repete.
Exemplos:
Exemplo 1:
>cat file
O gato preto foi caçado por um cachorro marrom.
>sed -e 's/preto/branco/g' file
O gato branco foi caçado por um cachorro marrom.
Exemplo 2:
>cat file
O gato preto foi caçado por um cachorro marrom.
O gato preto não foi caçado por um cachorro marrom.
>sed -e '/não/s/preto/branco/g' file
O gato preto foi caçado por um cachorro marrom.
O gato branco não caçado por um cachorro marrom.
Neste caso, a substituição é aplicada somente a linhas que casam com a expressão regular
"/não/". Portanto, ela não é aplicada a primeira linha, pois esta não contem a palavra "não".
Exemplo 3:
>cat file
linha 1 (um)
linha 2 (dois)
linha 3 (três)
Exemplo 3a:
>sed -e '1,2d' file
linha 3 (três)
Exemplo 3b:
>sed -e '3d' file
linha 1 (um)
linha 2 (dois)
Exemplo 3c:
>sed -e '1,2s/linha/LINHA/' file
LINHA 1 (um)
LINHA 2 (dois)
linha 3 (três)
Exemplo 3d:
>sed -e '/^linha.*um/s/linha/LINHA/' -e '/linha/d' file
LINHA 1 (um)
3a : Este foi bem simples: Nós apenas deletamos as linhas de 1 até 2
3b : Isto também foi simples: Nós deletamos a linha 3.
3c : Neste exemplo, nós fizemos uma substituição nas linhas 1 até 2.
3d : Agora este é mais interessante e merece algumas explicações.
O primeiro comando vai procurar "^linha.*um" e substituir "linha" por "LINHA", ou seja,
somente a primeira linha casa com essa expressão regular. O segundo comando diz para o sed
deletar linhas que contenham a palavra "linha". Assim, somente as duas últimas linhas serão
deletadas, já que a primeira teve palavra "linha" substituída por "LINHA".
Exemplo 4:
>cat file
olá
Este texto será cortado
olá (também será retirado)
ReTiRaDo Também!!!
tchau
(1) Este texto não foi apagado
(2) nem este ... ( tchau )
(3) nem este
olá
mas este será
e este também
e a menos que nós encontremos outro tch*u
cada linha até o final do texto será apagada
>sed -e '/olá/,/tchau/d' file
(1) Este texto não foi apagado
(2) nem este ... ( tchau )
(3) nem este
Isto mostra como o endereçamento funciona quando dois endereços são especificados. O sed
encontra o primeiro casamento da expressão "olá" e deleta todas as linhas lidas na área de
edição até ele encontrar a primeira linha que contém a expressão "tchau" (está também será
apagada). Ele não aplica mais o comando de deleção para nenhuma linha até encontrar
novamente a expressão "olá". Desde que a expressão "tchau" não ocorre mais em nenhuma
linha subseqüente, o comando de deleção é aplicado até o final do texto.
Resumindo, é simples: Quando ele encontra o primeiro endereço ("olá") ele passa a executar os
comandos até encontrar o segundo endereço ("tchau") ou o fim do texto. E isso se repete até
acabar o texto.
Exemplo 5:
>cat file
http://www.kernel.org/
>sed -e 's@http://www.kernel.org@http://www.metalab.unc.edu@' file
http://www.metalab.unc.edu/
Note que nós usamos um delimitador diferente, @ para o comando de substituição. O Sed
permite diversos delimitadores para o comando de substituição, incluindo @ % , ; : Esses
delimitadores alternativos são bons para substituições que incluem string como nome de
arquivos e outras que contém barra normal /, o que torna o código do sed muito mais legível.
Mais alguns comandos
Aqui veremos mais alguns comandos sobre o sed, a maioria deles mais complexos. Dependendo
da aplicação em que vocês forem usar o sed, dificilmente usarão esses recursos, a menos que
precisem de um processamento de texto mais refinado e complexo. Veja que eles são muito
usado nos scripts do sed (não confunda com shell-script). Backreference no Sed: Uma das
coisas legais sobre backreference no sed é que você pode usar não apenas em procura de textos
mas também na substituição de textos. O comando Quit: O comando quit ou "q" é muito
simples. Ele simplesmente termina o processamento. Nenhuma outra linha é lida para a área de
edição ou impressa na saída padrão. Sub-rotinas: Nós agora introduzimos o conceito de sub-
rotinas no sed:
No sed, as chaves { } são usadas para agrupar comandos. Elas são usadas dessa maneira:
endereço1[,endereço2]{
comandos}
Exemplo: Encontrar uma palavra de uma lista num arquivo
Este exemplo faz um bom uso dos conceitos descritos acima.
Para isto, nos usamos um shell-script, desde que os comandos são muito longos e precisaríamos
escrever a longa string X várias vezes. Note que usamos aspas duplas, já que a variável $X
precisa ser expandida pelo shell. A sintaxe para rodar esse script é: "script arquivo", onde
"script" é o nome dado ao script e "arquivo" é o nome do arquivo a procurar uma palavra da
lista.
#!/bin/sh
X='word1|word2|word3|word4|word5'
sed -e "
/$X/!d
/$X/{
s/($X).*/1/
s/.*($X)/1/
q
}" $1
Uma nota importante: é tentador pensar que:
s/($X).*/1/
s/.*($X)/1/
é redundante e tentar encurta-la para:
s/.*($X).*/1/
Mas isto não funciona. Por que? Suponha que temos a linha:
word1 word2 word3
Nós não temos como saber se $X vai casar com word1, word2 ou word3, então quando nós
citamos ele (1), nós não sabemos quais dos termos está sendo citado. O que está sendo usado
para certificar-se que não há problemas na correta implementação, é isto:
"O operador * é guloso. Ou seja, quando há ambigüidade sobre qual (expressão)* pode casar,
ele tentar casar o máximo possível."
Então neste exemplo, s/($X).*/1/ , .* tenta engolir o máximo da linha possível, em particular,
se a linha contém isso:
"word1 word2 word3"
Então nós podemos ter certeza que .* casa com " word2 word3" e portanto $X seria word1. Não
se preocupem se não entenderam muito bem este tópico. Ele é complicado mesmo e pouco
usado. O importante é entender como ele funciona, o uso de regexp e do comando de
substituição e deleção. Para maiores informações sobre o sed, dê uma olhada na sua man page:
"man sed"
Espero que vocês tenham gostado desse pequeno tutorial sobre sed. Como disse na aula
anterior sobre o Grip, é praticando que se aprende a usa-lo.
O fim...
Bom pessoal, acho que nosso curso termina por aqui. Claro que não deu pra cobrir tudo sobre
shell script, se não nosso curso não teria fim. Tentei abordar os topicos mais importantes, de
modo que vcs tenham uma boa noção de como funciona as coisas no shell e possam dar os
proprios passos. Desculpem se esqueci de falar sobre alguma coisa que vocês estavam
esperando. Como disse, estou a disposição para resolver qualquer dúvidas.

Mais conteúdo relacionado

Mais procurados

Introdução ao Linux - aula 03 e 04
Introdução ao Linux - aula 03 e 04Introdução ao Linux - aula 03 e 04
Introdução ao Linux - aula 03 e 04Renan Aryel
 
Shell Script - Luz e trevas
Shell Script - Luz e trevasShell Script - Luz e trevas
Shell Script - Luz e trevasOsvaldo Filho
 
Manual comandos
Manual comandosManual comandos
Manual comandosPaulo Rijo
 
Comandos básicos linux
Comandos básicos linuxComandos básicos linux
Comandos básicos linuxLuciano Souto
 
Introducao ao Shell Script
Introducao ao Shell ScriptIntroducao ao Shell Script
Introducao ao Shell ScriptHugo Maia Vieira
 
Introdução ao Shell Script (versão estendida)
Introdução ao Shell Script (versão estendida)Introdução ao Shell Script (versão estendida)
Introdução ao Shell Script (versão estendida)Hugo Maia Vieira
 
Curso de Shell Script 06/11
Curso de Shell Script 06/11Curso de Shell Script 06/11
Curso de Shell Script 06/11Rodrigo Silva
 
Soa cap2 exercicios resolvidos shell
Soa cap2 exercicios resolvidos shellSoa cap2 exercicios resolvidos shell
Soa cap2 exercicios resolvidos shellportal_Do_estudante
 
44087090 tutorial-programacao-batch
44087090 tutorial-programacao-batch44087090 tutorial-programacao-batch
44087090 tutorial-programacao-batchMarcio Pereira
 
Cap1 exercicios comandos linux resolucao part i
Cap1 exercicios comandos linux   resolucao part iCap1 exercicios comandos linux   resolucao part i
Cap1 exercicios comandos linux resolucao part iportal_Do_estudante
 
O Que é Shell (bash)
O Que é Shell (bash)O Que é Shell (bash)
O Que é Shell (bash)Sérgio Silva
 
Introdução à Shellscript
Introdução à ShellscriptIntrodução à Shellscript
Introdução à ShellscriptVinícius Hax
 
Shell script do zero aula 1 - basico do basico e primeiros comandos
Shell script do zero    aula 1 - basico do basico e primeiros comandosShell script do zero    aula 1 - basico do basico e primeiros comandos
Shell script do zero aula 1 - basico do basico e primeiros comandosIvan Ribeiro
 

Mais procurados (19)

Introdução ao Linux - aula 03 e 04
Introdução ao Linux - aula 03 e 04Introdução ao Linux - aula 03 e 04
Introdução ao Linux - aula 03 e 04
 
Shell Script - Luz e trevas
Shell Script - Luz e trevasShell Script - Luz e trevas
Shell Script - Luz e trevas
 
Manual comandos
Manual comandosManual comandos
Manual comandos
 
Curso gratuitoshellscript nivel-2
Curso gratuitoshellscript nivel-2Curso gratuitoshellscript nivel-2
Curso gratuitoshellscript nivel-2
 
Stack based overflow
Stack based overflowStack based overflow
Stack based overflow
 
Comandos básicos linux
Comandos básicos linuxComandos básicos linux
Comandos básicos linux
 
Cap1 exercicios comandos linux
Cap1 exercicios comandos linuxCap1 exercicios comandos linux
Cap1 exercicios comandos linux
 
Introducao ao Shell Script
Introducao ao Shell ScriptIntroducao ao Shell Script
Introducao ao Shell Script
 
Introdução ao Shell Script (versão estendida)
Introdução ao Shell Script (versão estendida)Introdução ao Shell Script (versão estendida)
Introdução ao Shell Script (versão estendida)
 
Curso de Shell Script 06/11
Curso de Shell Script 06/11Curso de Shell Script 06/11
Curso de Shell Script 06/11
 
Comandos basicos linux
Comandos basicos linuxComandos basicos linux
Comandos basicos linux
 
Soa cap2 exercicios resolvidos shell
Soa cap2 exercicios resolvidos shellSoa cap2 exercicios resolvidos shell
Soa cap2 exercicios resolvidos shell
 
Comandos linux
Comandos linuxComandos linux
Comandos linux
 
44087090 tutorial-programacao-batch
44087090 tutorial-programacao-batch44087090 tutorial-programacao-batch
44087090 tutorial-programacao-batch
 
Cap1 exercicios comandos linux resolucao part i
Cap1 exercicios comandos linux   resolucao part iCap1 exercicios comandos linux   resolucao part i
Cap1 exercicios comandos linux resolucao part i
 
O Que é Shell (bash)
O Que é Shell (bash)O Que é Shell (bash)
O Que é Shell (bash)
 
Introdução à Shellscript
Introdução à ShellscriptIntrodução à Shellscript
Introdução à Shellscript
 
Aprendendo linux
Aprendendo linuxAprendendo linux
Aprendendo linux
 
Shell script do zero aula 1 - basico do basico e primeiros comandos
Shell script do zero    aula 1 - basico do basico e primeiros comandosShell script do zero    aula 1 - basico do basico e primeiros comandos
Shell script do zero aula 1 - basico do basico e primeiros comandos
 

Destaque

Mrtg
MrtgMrtg
Mrtgmrtg
 
Monitoramento
MonitoramentoMonitoramento
MonitoramentoTiago
 
RAGHUNATH_KARAK_RESUME[1]
RAGHUNATH_KARAK_RESUME[1]RAGHUNATH_KARAK_RESUME[1]
RAGHUNATH_KARAK_RESUME[1]Raghunath Karak
 
Curso python
Curso pythonCurso python
Curso pythonTiago
 
Робота МО вчителів початкових класів у фотографіях. 2 частина
Робота МО вчителів початкових класів у фотографіях. 2 частинаРобота МО вчителів початкових класів у фотографіях. 2 частина
Робота МО вчителів початкових класів у фотографіях. 2 частинаAlusya
 
Wx python
Wx pythonWx python
Wx pythonTiago
 
Penal delitos contra las buenas costumbres
Penal delitos contra las buenas costumbresPenal delitos contra las buenas costumbres
Penal delitos contra las buenas costumbresal3jandravp
 
Cv Sulaiman Alnaimat cv (oct 2016) doc
Cv Sulaiman Alnaimat cv (oct 2016) docCv Sulaiman Alnaimat cv (oct 2016) doc
Cv Sulaiman Alnaimat cv (oct 2016) docSulaiman Alnaimat
 
Sleep Study Interpretation
Sleep Study InterpretationSleep Study Interpretation
Sleep Study Interpretationfracpractice
 
Ponencia presentada en evento mintrabajo jerarquizacion controles carlos vida...
Ponencia presentada en evento mintrabajo jerarquizacion controles carlos vida...Ponencia presentada en evento mintrabajo jerarquizacion controles carlos vida...
Ponencia presentada en evento mintrabajo jerarquizacion controles carlos vida...Redcayra Group Services F
 
Arquitetura ibm pc
Arquitetura ibm pcArquitetura ibm pc
Arquitetura ibm pcTiago
 

Destaque (12)

Mrtg
MrtgMrtg
Mrtg
 
Diapositivas men
Diapositivas menDiapositivas men
Diapositivas men
 
Monitoramento
MonitoramentoMonitoramento
Monitoramento
 
RAGHUNATH_KARAK_RESUME[1]
RAGHUNATH_KARAK_RESUME[1]RAGHUNATH_KARAK_RESUME[1]
RAGHUNATH_KARAK_RESUME[1]
 
Curso python
Curso pythonCurso python
Curso python
 
Робота МО вчителів початкових класів у фотографіях. 2 частина
Робота МО вчителів початкових класів у фотографіях. 2 частинаРобота МО вчителів початкових класів у фотографіях. 2 частина
Робота МО вчителів початкових класів у фотографіях. 2 частина
 
Wx python
Wx pythonWx python
Wx python
 
Penal delitos contra las buenas costumbres
Penal delitos contra las buenas costumbresPenal delitos contra las buenas costumbres
Penal delitos contra las buenas costumbres
 
Cv Sulaiman Alnaimat cv (oct 2016) doc
Cv Sulaiman Alnaimat cv (oct 2016) docCv Sulaiman Alnaimat cv (oct 2016) doc
Cv Sulaiman Alnaimat cv (oct 2016) doc
 
Sleep Study Interpretation
Sleep Study InterpretationSleep Study Interpretation
Sleep Study Interpretation
 
Ponencia presentada en evento mintrabajo jerarquizacion controles carlos vida...
Ponencia presentada en evento mintrabajo jerarquizacion controles carlos vida...Ponencia presentada en evento mintrabajo jerarquizacion controles carlos vida...
Ponencia presentada en evento mintrabajo jerarquizacion controles carlos vida...
 
Arquitetura ibm pc
Arquitetura ibm pcArquitetura ibm pc
Arquitetura ibm pc
 

Semelhante a Curso de shell

Curso de ShellScript - Lm05 shellscript5
Curso de ShellScript - Lm05 shellscript5Curso de ShellScript - Lm05 shellscript5
Curso de ShellScript - Lm05 shellscript5Pessoal
 
Introdução ao shell script no linux
Introdução ao shell script no linuxIntrodução ao shell script no linux
Introdução ao shell script no linuxPaulo Damas
 
Curso de ShellScript - Lm06 shellscript6
Curso de ShellScript - Lm06 shellscript6Curso de ShellScript - Lm06 shellscript6
Curso de ShellScript - Lm06 shellscript6Pessoal
 
01 apostila-introducao-shell
01   apostila-introducao-shell01   apostila-introducao-shell
01 apostila-introducao-shellvinicius caldeira
 
Funcionamento kernel
Funcionamento kernelFuncionamento kernel
Funcionamento kernelSENAC RIO
 
Curso De Shell Aula 3
Curso De Shell   Aula 3Curso De Shell   Aula 3
Curso De Shell Aula 3Felipe Santos
 
Curso de ShellScript - Lm01 shellscript
Curso de ShellScript - Lm01 shellscriptCurso de ShellScript - Lm01 shellscript
Curso de ShellScript - Lm01 shellscriptPessoal
 
Oficina shell
Oficina shellOficina shell
Oficina shellapsegundo
 
Bash, o poder da linha de comando! - Tchelinux.org 2017
Bash, o poder da linha de comando! - Tchelinux.org 2017Bash, o poder da linha de comando! - Tchelinux.org 2017
Bash, o poder da linha de comando! - Tchelinux.org 2017Sandro Custodio
 
Lab so-abertos-unidade15
Lab so-abertos-unidade15Lab so-abertos-unidade15
Lab so-abertos-unidade15Leandro Almeida
 
O Que é shell - bash
O Que é shell - bashO Que é shell - bash
O Que é shell - bashSérgio Silva
 
Oficina de shell script
Oficina de shell scriptOficina de shell script
Oficina de shell scriptbrunobione
 
Operadores de redirecionamento
Operadores de redirecionamentoOperadores de redirecionamento
Operadores de redirecionamentoIvani Nascimento
 
Apostila introducao-shell
Apostila introducao-shellApostila introducao-shell
Apostila introducao-shellMarcio Pereira
 
Laboratório de Programação I: Arquivos (texto) em disco
Laboratório de Programação I: Arquivos (texto) em discoLaboratório de Programação I: Arquivos (texto) em disco
Laboratório de Programação I: Arquivos (texto) em discoAlex Camargo
 

Semelhante a Curso de shell (20)

Lpi+102
Lpi+102Lpi+102
Lpi+102
 
Curso de ShellScript - Lm05 shellscript5
Curso de ShellScript - Lm05 shellscript5Curso de ShellScript - Lm05 shellscript5
Curso de ShellScript - Lm05 shellscript5
 
Shell script
Shell script Shell script
Shell script
 
Linux shell
Linux shellLinux shell
Linux shell
 
Introdução ao shell script no linux
Introdução ao shell script no linuxIntrodução ao shell script no linux
Introdução ao shell script no linux
 
Curso de ShellScript - Lm06 shellscript6
Curso de ShellScript - Lm06 shellscript6Curso de ShellScript - Lm06 shellscript6
Curso de ShellScript - Lm06 shellscript6
 
01 apostila-introducao-shell
01   apostila-introducao-shell01   apostila-introducao-shell
01 apostila-introducao-shell
 
Apostila introducao-shell
Apostila introducao-shellApostila introducao-shell
Apostila introducao-shell
 
Unidade 3.6 Introdução ao Shell
Unidade 3.6 Introdução ao ShellUnidade 3.6 Introdução ao Shell
Unidade 3.6 Introdução ao Shell
 
Funcionamento kernel
Funcionamento kernelFuncionamento kernel
Funcionamento kernel
 
Curso De Shell Aula 3
Curso De Shell   Aula 3Curso De Shell   Aula 3
Curso De Shell Aula 3
 
Curso de ShellScript - Lm01 shellscript
Curso de ShellScript - Lm01 shellscriptCurso de ShellScript - Lm01 shellscript
Curso de ShellScript - Lm01 shellscript
 
Oficina shell
Oficina shellOficina shell
Oficina shell
 
Bash, o poder da linha de comando! - Tchelinux.org 2017
Bash, o poder da linha de comando! - Tchelinux.org 2017Bash, o poder da linha de comando! - Tchelinux.org 2017
Bash, o poder da linha de comando! - Tchelinux.org 2017
 
Lab so-abertos-unidade15
Lab so-abertos-unidade15Lab so-abertos-unidade15
Lab so-abertos-unidade15
 
O Que é shell - bash
O Que é shell - bashO Que é shell - bash
O Que é shell - bash
 
Oficina de shell script
Oficina de shell scriptOficina de shell script
Oficina de shell script
 
Operadores de redirecionamento
Operadores de redirecionamentoOperadores de redirecionamento
Operadores de redirecionamento
 
Apostila introducao-shell
Apostila introducao-shellApostila introducao-shell
Apostila introducao-shell
 
Laboratório de Programação I: Arquivos (texto) em disco
Laboratório de Programação I: Arquivos (texto) em discoLaboratório de Programação I: Arquivos (texto) em disco
Laboratório de Programação I: Arquivos (texto) em disco
 

Mais de Tiago

Programacao php moodle
Programacao php moodleProgramacao php moodle
Programacao php moodleTiago
 
Apostila cdtc dotproject
Apostila cdtc dotprojectApostila cdtc dotproject
Apostila cdtc dotprojectTiago
 
6572501 ldp-apostila-de-turbo-pascal
6572501 ldp-apostila-de-turbo-pascal6572501 ldp-apostila-de-turbo-pascal
6572501 ldp-apostila-de-turbo-pascalTiago
 
Guia rapido de_pascal
Guia rapido de_pascalGuia rapido de_pascal
Guia rapido de_pascalTiago
 
Python bge
Python bgePython bge
Python bgeTiago
 
Curso python
Curso pythonCurso python
Curso pythonTiago
 
Aula 01 python
Aula 01 pythonAula 01 python
Aula 01 pythonTiago
 
Threading in c_sharp
Threading in c_sharpThreading in c_sharp
Threading in c_sharpTiago
 
Retirar acentos de_determinado_texto_em_c_sharp
Retirar acentos de_determinado_texto_em_c_sharpRetirar acentos de_determinado_texto_em_c_sharp
Retirar acentos de_determinado_texto_em_c_sharpTiago
 
Remover caracteres especiais_texto_em_c_sharp
Remover caracteres especiais_texto_em_c_sharpRemover caracteres especiais_texto_em_c_sharp
Remover caracteres especiais_texto_em_c_sharpTiago
 
Obter ip da_internet_em_c_sharp
Obter ip da_internet_em_c_sharpObter ip da_internet_em_c_sharp
Obter ip da_internet_em_c_sharpTiago
 
Metodo using no_c_sharp
Metodo using no_c_sharpMetodo using no_c_sharp
Metodo using no_c_sharpTiago
 
Introdução ao c# para iniciantes
Introdução ao c# para iniciantesIntrodução ao c# para iniciantes
Introdução ao c# para iniciantesTiago
 
Interfaces windows em c sharp
Interfaces windows em c sharpInterfaces windows em c sharp
Interfaces windows em c sharpTiago
 
Filestream sistema arquivos
Filestream  sistema arquivosFilestream  sistema arquivos
Filestream sistema arquivosTiago
 
Curso linux professor rafael
Curso linux professor rafaelCurso linux professor rafael
Curso linux professor rafaelTiago
 
Controle lpt em_c_sharp
Controle lpt em_c_sharpControle lpt em_c_sharp
Controle lpt em_c_sharpTiago
 
Classes csharp
Classes csharpClasses csharp
Classes csharpTiago
 
C# o basico
C#   o basicoC#   o basico
C# o basicoTiago
 
C# classes
C#   classesC#   classes
C# classesTiago
 

Mais de Tiago (20)

Programacao php moodle
Programacao php moodleProgramacao php moodle
Programacao php moodle
 
Apostila cdtc dotproject
Apostila cdtc dotprojectApostila cdtc dotproject
Apostila cdtc dotproject
 
6572501 ldp-apostila-de-turbo-pascal
6572501 ldp-apostila-de-turbo-pascal6572501 ldp-apostila-de-turbo-pascal
6572501 ldp-apostila-de-turbo-pascal
 
Guia rapido de_pascal
Guia rapido de_pascalGuia rapido de_pascal
Guia rapido de_pascal
 
Python bge
Python bgePython bge
Python bge
 
Curso python
Curso pythonCurso python
Curso python
 
Aula 01 python
Aula 01 pythonAula 01 python
Aula 01 python
 
Threading in c_sharp
Threading in c_sharpThreading in c_sharp
Threading in c_sharp
 
Retirar acentos de_determinado_texto_em_c_sharp
Retirar acentos de_determinado_texto_em_c_sharpRetirar acentos de_determinado_texto_em_c_sharp
Retirar acentos de_determinado_texto_em_c_sharp
 
Remover caracteres especiais_texto_em_c_sharp
Remover caracteres especiais_texto_em_c_sharpRemover caracteres especiais_texto_em_c_sharp
Remover caracteres especiais_texto_em_c_sharp
 
Obter ip da_internet_em_c_sharp
Obter ip da_internet_em_c_sharpObter ip da_internet_em_c_sharp
Obter ip da_internet_em_c_sharp
 
Metodo using no_c_sharp
Metodo using no_c_sharpMetodo using no_c_sharp
Metodo using no_c_sharp
 
Introdução ao c# para iniciantes
Introdução ao c# para iniciantesIntrodução ao c# para iniciantes
Introdução ao c# para iniciantes
 
Interfaces windows em c sharp
Interfaces windows em c sharpInterfaces windows em c sharp
Interfaces windows em c sharp
 
Filestream sistema arquivos
Filestream  sistema arquivosFilestream  sistema arquivos
Filestream sistema arquivos
 
Curso linux professor rafael
Curso linux professor rafaelCurso linux professor rafael
Curso linux professor rafael
 
Controle lpt em_c_sharp
Controle lpt em_c_sharpControle lpt em_c_sharp
Controle lpt em_c_sharp
 
Classes csharp
Classes csharpClasses csharp
Classes csharp
 
C# o basico
C#   o basicoC#   o basico
C# o basico
 
C# classes
C#   classesC#   classes
C# classes
 

Último

apostila projeto de vida 2 ano ensino médio
apostila projeto de vida 2 ano ensino médioapostila projeto de vida 2 ano ensino médio
apostila projeto de vida 2 ano ensino médiorosenilrucks
 
Dicionário de Genealogia, autor Gilber Rubim Rangel
Dicionário de Genealogia, autor Gilber Rubim RangelDicionário de Genealogia, autor Gilber Rubim Rangel
Dicionário de Genealogia, autor Gilber Rubim RangelGilber Rubim Rangel
 
Considere a seguinte situação fictícia: Durante uma reunião de equipe em uma...
Considere a seguinte situação fictícia:  Durante uma reunião de equipe em uma...Considere a seguinte situação fictícia:  Durante uma reunião de equipe em uma...
Considere a seguinte situação fictícia: Durante uma reunião de equipe em uma...azulassessoria9
 
Rota das Ribeiras Camp, Projeto Nós Propomos!
Rota das Ribeiras Camp, Projeto Nós Propomos!Rota das Ribeiras Camp, Projeto Nós Propomos!
Rota das Ribeiras Camp, Projeto Nós Propomos!Ilda Bicacro
 
INTERVENÇÃO PARÁ - Formação de Professor
INTERVENÇÃO PARÁ - Formação de ProfessorINTERVENÇÃO PARÁ - Formação de Professor
INTERVENÇÃO PARÁ - Formação de ProfessorEdvanirCosta
 
Historia da Arte europeia e não só. .pdf
Historia da Arte europeia e não só. .pdfHistoria da Arte europeia e não só. .pdf
Historia da Arte europeia e não só. .pdfEmanuel Pio
 
Urso Castanho, Urso Castanho, o que vês aqui?
Urso Castanho, Urso Castanho, o que vês aqui?Urso Castanho, Urso Castanho, o que vês aqui?
Urso Castanho, Urso Castanho, o que vês aqui?AnabelaGuerreiro7
 
Música Meu Abrigo - Texto e atividade
Música   Meu   Abrigo  -   Texto e atividadeMúsica   Meu   Abrigo  -   Texto e atividade
Música Meu Abrigo - Texto e atividadeMary Alvarenga
 
PROVA - ESTUDO CONTEMPORÂNEO E TRANSVERSAL: COMUNICAÇÃO ASSERTIVA E INTERPESS...
PROVA - ESTUDO CONTEMPORÂNEO E TRANSVERSAL: COMUNICAÇÃO ASSERTIVA E INTERPESS...PROVA - ESTUDO CONTEMPORÂNEO E TRANSVERSAL: COMUNICAÇÃO ASSERTIVA E INTERPESS...
PROVA - ESTUDO CONTEMPORÂNEO E TRANSVERSAL: COMUNICAÇÃO ASSERTIVA E INTERPESS...azulassessoria9
 
Ficha de trabalho com palavras- simples e complexas.pdf
Ficha de trabalho com palavras- simples e complexas.pdfFicha de trabalho com palavras- simples e complexas.pdf
Ficha de trabalho com palavras- simples e complexas.pdfFtimaMoreira35
 
COMPETÊNCIA 4 NO ENEM: O TEXTO E SUAS AMARRACÕES
COMPETÊNCIA 4 NO ENEM: O TEXTO E SUAS AMARRACÕESCOMPETÊNCIA 4 NO ENEM: O TEXTO E SUAS AMARRACÕES
COMPETÊNCIA 4 NO ENEM: O TEXTO E SUAS AMARRACÕESEduardaReis50
 
JOGO FATO OU FAKE - ATIVIDADE LUDICA(1).pptx
JOGO FATO OU FAKE - ATIVIDADE LUDICA(1).pptxJOGO FATO OU FAKE - ATIVIDADE LUDICA(1).pptx
JOGO FATO OU FAKE - ATIVIDADE LUDICA(1).pptxTainTorres4
 
421243121-Apostila-Ensino-Religioso-Do-1-ao-5-ano.pdf
421243121-Apostila-Ensino-Religioso-Do-1-ao-5-ano.pdf421243121-Apostila-Ensino-Religioso-Do-1-ao-5-ano.pdf
421243121-Apostila-Ensino-Religioso-Do-1-ao-5-ano.pdfLeloIurk1
 
Construção (C)erta - Nós Propomos! Sertã
Construção (C)erta - Nós Propomos! SertãConstrução (C)erta - Nós Propomos! Sertã
Construção (C)erta - Nós Propomos! SertãIlda Bicacro
 
PRÁTICAS PEDAGÓGICAS GESTÃO DA APRENDIZAGEM
PRÁTICAS PEDAGÓGICAS GESTÃO DA APRENDIZAGEMPRÁTICAS PEDAGÓGICAS GESTÃO DA APRENDIZAGEM
PRÁTICAS PEDAGÓGICAS GESTÃO DA APRENDIZAGEMHELENO FAVACHO
 
Slides Lição 05, Central Gospel, A Grande Tribulação, 1Tr24.pptx
Slides Lição 05, Central Gospel, A Grande Tribulação, 1Tr24.pptxSlides Lição 05, Central Gospel, A Grande Tribulação, 1Tr24.pptx
Slides Lição 05, Central Gospel, A Grande Tribulação, 1Tr24.pptxLuizHenriquedeAlmeid6
 
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdfPROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdfHELENO FAVACHO
 
Análise poema país de abril (Mauel alegre)
Análise poema país de abril (Mauel alegre)Análise poema país de abril (Mauel alegre)
Análise poema país de abril (Mauel alegre)ElliotFerreira
 
planejamento_estrategico_-_gestao_2021-2024_16015654.pdf
planejamento_estrategico_-_gestao_2021-2024_16015654.pdfplanejamento_estrategico_-_gestao_2021-2024_16015654.pdf
planejamento_estrategico_-_gestao_2021-2024_16015654.pdfmaurocesarpaesalmeid
 

Último (20)

apostila projeto de vida 2 ano ensino médio
apostila projeto de vida 2 ano ensino médioapostila projeto de vida 2 ano ensino médio
apostila projeto de vida 2 ano ensino médio
 
Dicionário de Genealogia, autor Gilber Rubim Rangel
Dicionário de Genealogia, autor Gilber Rubim RangelDicionário de Genealogia, autor Gilber Rubim Rangel
Dicionário de Genealogia, autor Gilber Rubim Rangel
 
Considere a seguinte situação fictícia: Durante uma reunião de equipe em uma...
Considere a seguinte situação fictícia:  Durante uma reunião de equipe em uma...Considere a seguinte situação fictícia:  Durante uma reunião de equipe em uma...
Considere a seguinte situação fictícia: Durante uma reunião de equipe em uma...
 
Rota das Ribeiras Camp, Projeto Nós Propomos!
Rota das Ribeiras Camp, Projeto Nós Propomos!Rota das Ribeiras Camp, Projeto Nós Propomos!
Rota das Ribeiras Camp, Projeto Nós Propomos!
 
INTERVENÇÃO PARÁ - Formação de Professor
INTERVENÇÃO PARÁ - Formação de ProfessorINTERVENÇÃO PARÁ - Formação de Professor
INTERVENÇÃO PARÁ - Formação de Professor
 
Historia da Arte europeia e não só. .pdf
Historia da Arte europeia e não só. .pdfHistoria da Arte europeia e não só. .pdf
Historia da Arte europeia e não só. .pdf
 
Urso Castanho, Urso Castanho, o que vês aqui?
Urso Castanho, Urso Castanho, o que vês aqui?Urso Castanho, Urso Castanho, o que vês aqui?
Urso Castanho, Urso Castanho, o que vês aqui?
 
Música Meu Abrigo - Texto e atividade
Música   Meu   Abrigo  -   Texto e atividadeMúsica   Meu   Abrigo  -   Texto e atividade
Música Meu Abrigo - Texto e atividade
 
PROVA - ESTUDO CONTEMPORÂNEO E TRANSVERSAL: COMUNICAÇÃO ASSERTIVA E INTERPESS...
PROVA - ESTUDO CONTEMPORÂNEO E TRANSVERSAL: COMUNICAÇÃO ASSERTIVA E INTERPESS...PROVA - ESTUDO CONTEMPORÂNEO E TRANSVERSAL: COMUNICAÇÃO ASSERTIVA E INTERPESS...
PROVA - ESTUDO CONTEMPORÂNEO E TRANSVERSAL: COMUNICAÇÃO ASSERTIVA E INTERPESS...
 
Ficha de trabalho com palavras- simples e complexas.pdf
Ficha de trabalho com palavras- simples e complexas.pdfFicha de trabalho com palavras- simples e complexas.pdf
Ficha de trabalho com palavras- simples e complexas.pdf
 
COMPETÊNCIA 4 NO ENEM: O TEXTO E SUAS AMARRACÕES
COMPETÊNCIA 4 NO ENEM: O TEXTO E SUAS AMARRACÕESCOMPETÊNCIA 4 NO ENEM: O TEXTO E SUAS AMARRACÕES
COMPETÊNCIA 4 NO ENEM: O TEXTO E SUAS AMARRACÕES
 
JOGO FATO OU FAKE - ATIVIDADE LUDICA(1).pptx
JOGO FATO OU FAKE - ATIVIDADE LUDICA(1).pptxJOGO FATO OU FAKE - ATIVIDADE LUDICA(1).pptx
JOGO FATO OU FAKE - ATIVIDADE LUDICA(1).pptx
 
421243121-Apostila-Ensino-Religioso-Do-1-ao-5-ano.pdf
421243121-Apostila-Ensino-Religioso-Do-1-ao-5-ano.pdf421243121-Apostila-Ensino-Religioso-Do-1-ao-5-ano.pdf
421243121-Apostila-Ensino-Religioso-Do-1-ao-5-ano.pdf
 
Construção (C)erta - Nós Propomos! Sertã
Construção (C)erta - Nós Propomos! SertãConstrução (C)erta - Nós Propomos! Sertã
Construção (C)erta - Nós Propomos! Sertã
 
PRÁTICAS PEDAGÓGICAS GESTÃO DA APRENDIZAGEM
PRÁTICAS PEDAGÓGICAS GESTÃO DA APRENDIZAGEMPRÁTICAS PEDAGÓGICAS GESTÃO DA APRENDIZAGEM
PRÁTICAS PEDAGÓGICAS GESTÃO DA APRENDIZAGEM
 
Slides Lição 05, Central Gospel, A Grande Tribulação, 1Tr24.pptx
Slides Lição 05, Central Gospel, A Grande Tribulação, 1Tr24.pptxSlides Lição 05, Central Gospel, A Grande Tribulação, 1Tr24.pptx
Slides Lição 05, Central Gospel, A Grande Tribulação, 1Tr24.pptx
 
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdfPROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
 
Análise poema país de abril (Mauel alegre)
Análise poema país de abril (Mauel alegre)Análise poema país de abril (Mauel alegre)
Análise poema país de abril (Mauel alegre)
 
planejamento_estrategico_-_gestao_2021-2024_16015654.pdf
planejamento_estrategico_-_gestao_2021-2024_16015654.pdfplanejamento_estrategico_-_gestao_2021-2024_16015654.pdf
planejamento_estrategico_-_gestao_2021-2024_16015654.pdf
 
CINEMATICA DE LOS MATERIALES Y PARTICULA
CINEMATICA DE LOS MATERIALES Y PARTICULACINEMATICA DE LOS MATERIALES Y PARTICULA
CINEMATICA DE LOS MATERIALES Y PARTICULA
 

Curso de shell

  • 1. Curso de Shell - Aula I Introdução O que são os shell scripts? Shell scripts são conjuntos de comandos armazenados em um arquivo texto que são executados seqüencialmente. Nesta primeira parte, faremos uma introdução sobre o shell, o formato desses arquivos e variáveis de ambiente. O que é Shell Shell, ou interpretador de comandos, é o programa disparado logo após o login responsável por "pegar" os comandos do usuário, interpretá-los e executar uma determinada ação. Por exemplo, quando você escreve no console "ls" e pressiona , o shell lê essa string e verifica se existe algum comando interno (embutido no próprio shell) com esse nome. Se houver, ele executa esse comando interno. Caso contrário, ele vai procurar no PATH por algum programa que tenha esse nome. Se encontrar, ele executa esse programa, caso contrário, ele retorna uma mensagem de erro. Para cada terminal ou console aberto, existe um shell sendo executado. Quando você entra no seu Linux, ele apresenta o login, para digitar o usuário e a senha. Ao digitar um par usuário/senha correto, o Linux abre automaticamente um shell, que vai ficar esperando seus comandos. Veja o exemplo abaixo: Welcome to Linux Slackware 7.1 kernel 2.2.16. matrix login: neo Password: Linux 2.2.16. Last login: Mon Sep 25 10:41:12 -0300 2000 on tty1. No mail. neo@matrix:~$ Essa ultima linha é o shell. Se você der o comando "ps", vai ver que um dos programas rodando é o seu shell: neo@matrix:~$ ps PID TTY TIME CMD 164 tty2 00:00:00 bash 213 tty2 00:00:00 ps neo@matrix:~$ Ou seja, o shell utilizado nesse console é o bash, que está rodando com PID 164. Existem diversos tipos de shell: bash, csh, ksh, ash, etc. O mais utilizado atualmente é o bash (GNU Bourne-Again SHell). Por isso, tomaremos ele como referência. Resumindo essa seção, é importante saber que para cada terminal ou console aberto, tem-se um shell rodando. Assim, se você tem 3 xterms abertos na interface gráfica, vai ter um shell para cada xterm. Ao executar o shell script, o shell atual (no qual você deu o comando) abre um novo shell para executar o script. Assim, os scripts são executados em um shell próprio (a menos que se especifique, ao chamar o script, para executá-lo no shell atual). Isso será importante quando formos tratar de variáveis de ambiente. Variáveis do ambiente Uma variável é onde o shell armazena determinados valores para utilização posterior.
  • 2. Toda variável possui um nome e um valor associado a ela, podendo ser este último vazio. Para listar as variáveis atualmente definidas no shell digite o comando set. Para se definir uma variável, basta utilizar a síntaxe: nome_da_variável=valor. Por exemplo, queremos definir uma variável chamada "cor" com o valor de "azul": neo@matrix:~$ cor=azul Para utilizar o valor de uma variável, é só colocar um sinal de "$" seguido do nome da variável - o shell automaticamente substitui pelo valor da variável: neo@matrix:~$ echo cor cor neo@matrix:~$ echo $cor azul Em alguns casos, é aconselhável colocar o nome da variável entre chaves ({}). Por exemplo, se eu quero imprimir "azul-escuro", como faria? Simplesmente echo $cor-escuro ?? Não funcionaria, pois o bash vai procurar uma variável de nome "cor-escuro". Portanto, temos que colocar o nome "cor" entre chaves para delimitar o nome da variável: neo@matrix:~$ echo ${cor}-escuro azul-escuro Algumas variáveis já são predefinidas no shell, como o PATH, que, como foi dito antes, armazena o caminho dos programas. Por exemplo, a minha variável PATH contém: neo@matrix:~$ echo $PATH /usr/local/bin:/usr/bin: /bin: /usr/X11R6/bin: /usr/openwin/bin: /usr/games: /opt/kde/bin: /usr/share/texmf/bin: /etc/script Ou seja, quando digito um comando, como "ls", o shell vai começar a procurá-lo em /usr/local/bin, se não encontrá-lo, vai procurar em /usr/bin e assim por diante. Repare que os diretórios são separados por um sinal de dois pontos (:). É importante destacar que o shell possui várias variáveis pré-definidas, ou seja, que possuem um significado especial para ele, entre elas: PATH, PWD, PS1, PS2, USER e UID. Assim, quando iniciamos um novo shell (ao executar o nosso script), essas variáveis especiais são "herdadas" do shell pai (o que executou o shell filho). Outras variáveis definidas pelo usuário, como a variável "cor" não são passadas do shell pai para o filho. Quando o script terminar, o seu shell (shell filho) simplesmente desaparece e com ele também as suas variáveis, liberando o espaço ocupado na memória. Formato dos arquivos de Shell Script A primeira linha de todo shell script deve começar com algo do tipo: #!/bin/bash, a qual indica com qual shell deverá ser executado o script. Nesse exemplo, estamos falando para o shell atual executar o script com o shell /bin/bash.Se quisermos que o nosso script seja executado com o shell csh, devemos colocar nessa primeira linha: #!/bin/csh. Como usaremos o bash como nosso shell de referência, todas as linhas dos nossos scripts começarão com #!/bin/bash.
  • 3. Digamos que você executa freqüentemente o comando: find / -name file -print, que procura na raiz (/) por um arquivo de nome "file". Só que é chato ficar digitando esse comando toda vez que se quer procurar um arquivo. Então vamos criar um shell script que contenha esse comando. Vamos chamar esse shell script de "procura". Seu conteúdo fica assim: #!/bin/bash find / -name file -print Pronto. Tornemos agora o arquivo executável: chmod 755 ./procura. Porém, ao tentar executar o nosso script, teremos um problema. ./procura Este script irá procurar por um arquivo chamado "file". Como especificar qual arquivo queremos procurar? Seria ideal executarmos o nosso script seguido do nome do arquivo que queremos procurar. Por exemplo, queremos saber onde está o arquivo "netscape": ./procura netscape. É ai que entram as "variáveis de parâmetro". Vamos substituir no nosso script a linha find / -name file -print por find / -name $1 -print. Quando o bash lê a variável "$1", ele a substitui pelo primeiro parâmetro passado na linha de comando para o nosso script. Então, se executamos ./procura netscape, a variável "$1" será substituída por "netscape", como a gente queria. Repare que a variável "$2" conteria o segundo parâmetro passado para o script e assim por diante. Sendo assim, qualquer comando colocado abaixo de find seria executado após ele. Esse é o essencial do shell script: poder automatizar a execução de programas e comandos como se estivessem sendo digitados diretamente no console ou terminal. Conclusão Na próxima aula do nosso curso de shell script iremos aprender alguns comandos especiais para tornar nossos script mais poderosos, fazendo coisas mais elaboradas do que apenas executar programas seqüencialmente. Entre eles, podemos destacar os comandos de laço, como "if", "for", "while", "case" etc. [por Alex Borro] Curso de Shell - Aula II Introdução Na aula de hoje vamos falar sobre execução de programas em primeiro plano (fg - foreground) e em segundo plano (bg - background), redirecionamento de saídas e também sobre os códigos de escape dos programas. Execução em foreground e background Quando executamos um programa, o shell fica esperando o mesmo terminar para depois nos devolver a linha de comando. Por exemplo, quando executamos o comando cp arquivo1 arquivo2,o shell executa esse comando, fica esperando ele terminar, para depois nos retornar a linha de comando. Isso chama-se execução em primeiro plano, ou foreground, em inglês.Agora digamos que o arquivo a ser copiado seja muito grande, digamos, 50Mb. Enquanto o comando cp é executado, vamos ficar com o shell preso a ele todo esse tempo, ou seja, cerca de 1 ou 2 minutos. Somente após isso vamos ter a linha de comando de volta para podermos continuar trabalhando. E se pudéssemos dizer ao shell para executar um programa e nos retornar a linha de comando sem ficar esperando o tal programa terminar? Seria muito melhor, não? Em alguns casos seria.
  • 4. E podemos fazer isso. Uma maneira fácil é colocar o sinal de & depois de um comando. No exemplo acima ficaria: neo@matrix:~$ cp arquivo1 arquivo2 & [1] 206 neo@matrix:~$ Pronto, assim que teclarmos [enter], teremos a nossa linha de comando de volta e mais duas informações: "[1] 206". A primeira informação ([1]) chama-se job. Ela identifica os programas que estão sendo executados em bg (background). Por exemplo, se executarmos mais um programa em bg enquanto este "cp" está sendo executado, o novo programa recebe o job de número 2 ([2]) e assim por diante. A segunda informação (206) é o pid do programa, ou seja, o número de processo que o kernel dá a esse programa. Mas aí temos um pequeno problema. Digamos que você queira trazer o programa para fg, por exemplo, se o programa executado em bg for um tocador de mp3 e você quiser mudar a música. Como fazemos? Usamos o comando fg [job] (intuitivo, não ?) do bash. No exemplo acima, digamos que eu execute o "cp" em bg, mas depois queira trazê-lo para fg para cancelá- lo. Seria simples: neo@matrix:~$ cp arquivo1 arquivo2 & [1] 206 neo@matrix:~$ fg 1 cp arquivo1 arquivo2 Assim trazemos o "cp" para primeiro plano e a linha de comando só retorna quando ele terminar. Opcional: Uma outra maneira de colocar um programa para rodar em bg é utilizando um truque do bash (não sei se esta opção está disponível em outros shells).Digamos que você execute o comando "cp" e esqueça de colocar o sinal "&". E aí? Tem que ficar esperando acabar ou cancelar o comando? Não, podemos teclar: Ctrl + Z. Ao fazer isso, paramos a execução do programa. Então é só dar o comando bg [job] (intuitivo também, né?): neo@matrix:~$ cp arquivo1 arquivo2 * aqui teclamos Ctrl + Z * [1]+ Stopped cp -i arquivo1 arquivo2 neo@matrix:~$ bg 1 [1]+ cp -i arquivo1 arquivo2 & neo@matrix:~$ Quando teclamos o Ctrl + Z, o bash nos diz que o job 1 foi parado ([1]+ Stopped) e quando executamos "bg 1" ele nos diz que o comando voltou a ser executado, mas em bg (repare o sinal de "&" no final da linha): [1]+ cp -i arquivo1 arquivo2 &. Redirecionamento de saídas Muitos programas que executamos geram saídas no console, ou sejam, emitem mensagens para os usuários. Por exemplo, queremos achar quantos arquivos no nosso sistema tem "netscape" no nome:
  • 5. neo@matrix:~$ find / -name netscape /usr/lib/netscape /usr/lib/netscape/netscape /usr/lib/netscape/nethelp/netscape /usr/local/bin/netscape Agora se quisermos procurar quantos arquivos compactados com o gzip (extensão .gz) tem no nosso sistema para depois analisá-los e possivelmente apagar os repetidos ou inúteis, teremos uma lista muito grande. Aqui no meu sistema deu mais de 1000 arquivos. Então, seria útil podermos enviar as mensagens que vão para o console, para um arquivo. Assim, poderíamos analisá-lo depois de executar o comando. Isso é extremamente útil ao trabalharmos com shell script - enviar as saídas dos comandos para arquivos para depois analisá-las. Exemplificando: neo@matrix:~$ find / -name "*.gz" > lista.txt find: /home/vera: Permissão negada find: /home/pri: Permissão negada find: /root: Permissão negada neo@matrix:~$ Notamos que nem tudo foi para o arquivo lista.txt. As mensagens de erro foram para o console. Isso porque existem dois tipos de saída: a saída padrão e a saída de erro.A saída padrão é a saída normal dos programas, que no caso acima, seria os arquivos encontrados. E a saída de erro, como o próprio nome diz, são os erro encontrados pelo programa durante sua execução, que devem ser informados ao usuário, como os erros de "permissão negada". E aí, como selecionar uma ou outra? É simples, apenas devemos indicar o "file descriptor" (fd) delas. Não vamos entrar em detalhes sobre o que é "descritor de arquivos" por fugir do nosso escopo e ser um pouco complicado, apenas temos que saber que o fd 1 corresponde a saída padrão e o fd 2 a saída de erro. Assim, no exemplo acima, para enviar os erro para o arquivo erros.txt e a saída padrão para o arquivo lista.txt, usaríamos: neo@matrix:~$ find / -name "*.gz" 1> lista.txt 2> erros.txt Ou seja, é só por o número da saída desejada antes do sinal de ">". Agora digamos que queremos ver o conteúdo do arquivo lista.txt. Podemos abrí-lo com um editor de textos ou usar o "cat". Optando pela última opção: neo@matrix:~$ cat lista.txt /home/neo/gkrellm-0.10.5.tar.gz /home/neo/linuxcall-interface-beta.tar.gz ... <<< mais de 1000 linhas neo@matrix:~$ Temos um problema. O arquivo tem mais de 1000 linhas e não conseguimos vê-lo inteiro. Podemos redirecionar a saída do comando "cat" para o comando "more", que dá pausa entre as telas: neo@matrix:~$ cat lista.txt | more ......... Veja que utilizamos o caractere "|", chamado "pipe". Não poderíamos ter utilizado o sinal de ">"? Não, o sinal de ">" é somente para enviar a saída para um ARQUIVO. Para enviar a saída de um comando para a entrada de outro, usamos o pipe.
  • 6. As vezes queremos que além da saída ir para um arquivo, ela também vá para a tela. Temos um programinha que faz isso. Ele chama-se "tee". Veja o exemplo a seguir: neo@matrix:~$ find / -name "*.gz" 2> erros.txt | tee lista.txt O que fizemos???Primeiro pegamos a saída de erro e enviamos para o arquivo erros.txt. O restante, ou seja, a saída padrão, estamos enviando para a entrada do comando tee (usando o pipe). O tee simplesmente pega o que ele recebe (através do pipe) e joga no arquivo lista.txt e na tela. Assim, além de gravarmos a saída num arquivo, podemos mostrar ao usuário o que está acontecendo. Isso é muito útil quando escrevemos alguns scripts. Resumindo: aprendemos que podemos redirecionar a saída padrão ou de erro de programa para um arquivo usando respectivamente "1>" ou "2>" ou também enviar a saída para a entrada de outro programa usando o pipe "|". Códigos de Escape Toda vez que executamos um programa em Unix, ele retorna um código de escape ao finalizar. Esse código reflete a condição em que o programa finalizou. Se ocorreu tudo certo e o programa terminou normalmente, ele retorna 0. Se ocorreu algum problema, o programa retorna um código diferente de 0, geralmente variando com o problema ocorrido. Esse código de retorno é extremamente importante em shell script, pois é assim que testamos se uma certa ação ocorreu bem ou teve problemas.Esse código é armazenado pelo bash numa variável chamada "?" (isso mesmo, somente o sinal de interrogação ;-)). Por exemplo, vamos executar um "ls" em um diretório que existe e ver o código de retorno: neo@matrix:~$ ls /boot System.map boot.0300 boot.b boot_message.txt chain.b config map os2_d.b neo@matrix:~$ echo $? 0 neo@matrix:~$ Ou seja, o "ls" foi executado normalmente, retornando 0. Agora vamos executá-lo num diretório que não existe: neo@matrix:~$ ls /diretorio_invalido /bin/ls: /diretorio_invalido: Arquivo ou diretório não encontrado neo@matrix:~$ echo $? 1 neo@matrix:~$ Como esperado, obtemos o retorno de erro 1. Alguns programas tem muitos códigos de retorno. Por exemplo, os códigos de retorno do "pppd" vão até o 19. Assim é possível saber porque ele foi finalizado. Se você colocar uma senha errada no pppd e tentar conectar, ele vai terminar com o código 19. man pppd ... 17 The PPP negotiation failed because serial loopback was detected. 18 The init script failed (returned a non-zero exit status). 19 We failed to authenticate ourselves to the peer. ...
  • 7. Um detalhe importante: quando executamos um programa em background, ele sempre retorna um código 0 para o shell, mesmo que durante sua execução ocorra algum problema. Assim, quando executamos um programa em bg, perdemos essa facilidade de testar como foi seu término. neo@matrix:~$ ls /diretorio_invalido & [1] 230 neo@matrix:~$ /bin/ls: /diretorio_invalido: Arquivo ou diretório não encontrado [1]+ Exit 1 /bin/ls $LS_OPTIONS /diretorio_invalido neo@matrix:~$ echo $? 0 Como vemos, ao terminar, ele emite uma mensagem dizendo que finalizou com código 1 ([1]+ Exit 1) mas quando testamos a variável "?", o bash nos diz "0". Conclusão Como todos os programas tem que terminar com um código de retorno que tenha algum significado, nossos shell scripts também terão que finalizar indicando o que aconteceu, se ocorreu tudo bem ou se ouve erro. Mas isso discutiremos melhor mais pra frente. O importante aqui é saber que todos os programas terminam com um código de retorno, os quais usaremos nos nossos scripts para testar o término dos programas. Curso de Shell - Aula III Introdução Nesta terceira parte do nosso curso de shell script, vamos tratar de "condicionais". Condicionais são comandos que avaliam uma expressão. Se ela for verdadeira, uma determinada rotina é executada. Caso contrário, outra rotina pode ser executada. O famoso "if" O bash nos oferece, entre outros, o comando IF (ele é um comando embutido no bash e não um programa como o "ls", o "cp" etc.). A forma mais simples de representar uma condicional utilizando o IF, é da seguinte forma básica: if [condição]; then comandos1; else comandos2; fi; Se [condição] for verdadeira, os comandos1 são executados. Se for falsa, os comandos2 são executados.Mas para o IF, o que é uma condição verdadeira ou uma falsa? Como foi explicado na aula anterior, TODO comando em Unix tem um código de retorno. Geralmente o código "0" (zero) significa que o comando foi executado perfeitamente e terminou bem. Códigos maiores que zero significam que alguma coisa de errado ocorreu. É assim que o IF verifica uma condição. Se o seu código de retorno for zero, então ela é considerada verdadeira. Caso contrario, ela é falsa.Mas então a [condição] tem que ser um comando, certo? Exatamente. Vamos exemplificar: neo@matrix:~$ if ls /boot; then echo "O diretório existe."; else echo "Diretório inválido.";
  • 8. fi; System.map boot.0300 boot.b boot_message.txt chain.b config map os2_d.b O diretório existe. O que fizemos? Logo após o if, nós colocamos um comando: "ls /boot". O que o IF faz? Ele executa esse comando (por isso que temos a segunda linha começada por "System.map", que é o conteúdo do meu diretório /boot) e avalia o seu código de saída. Como o "ls" foi executado corretamente, ele retorna zero, significando verdadeiro para o IF, que executa o comando logo após o "then", ou seja, o echo "O diretório existe.", mostrando essa mensagem no console. Agora vamos colocar um diretório que não existe: neo@matrix:~$ if ls /dir_invalido; then echo "O diretório existe."; else echo "Diretório inválido."; fi; /bin/ls: /dir_invalido: Arquivo ou diretório não encontrado Diretório inválido. A lógica é a mesma. Executa o "ls /dir_invalido", que retorna um código maior que zero. O IF avalia como falso e executa o comando após o else: echo "Diretório inválido". Nós poderíamos omitir a segunda linha dos dois exemplo (a que mostra o conteúdo de /boot no primeiro exemplo e a mensagem de erro emitida pelo ls dizendo que /dir_invalido não existe no segundo), apenas redirecionando as saídas para /dev/null, ou seja: neo@matrix:~$ ls /boot 1> /dev/null 2> /dev/null Nota: Tem um macete que possui o mesmo efeito. Em vez de colocar: "1> /dev/null 2> /dev/null" podemos colocar "2&>1", que é menor e mais simples. O comando "test" Bom, aprendemos que o IF avalia a código de retorno de um comando. Mas muitas vezes, para não dizer a maioria, nós queremos avaliar "expressões", ou seja, verificar se uma variável é igual a outra, se ela esta vazia etc. Para isso, nós temos outro comando chamado "test" (intuitivo o nome, não?). Ele funciona da seguinte maneira: test [expressão]. O test pode testar operações de três tipos: strings, arquivos e aritméticas. Expressões usando strings: O test pode apenas comparar strings, ou seja, verificar se uma é igual a outra, e verificar se uma string é vazia ou não. Vamos aos exemplos para facilitar o entendimento: neo@matrix:~$ test "a" = "a" neo@matrix:~$ echo $? 0 neo@matrix:~$ test "a" = "b" neo@matrix:~$ echo $? 1 neo@matrix:~$ test "a" != "b" neo@matrix:~$ echo $? 0
  • 9. Aqui comparamos a string "a" com "b". Como era de se esperar, o primeiro retornou verdadeiro (zero), pois a = a e o segundo retornou falso. No terceiro, o símbolo "!=" significa "diferente". neo@matrix:~$ test -z "neo" neo@matrix:~$ echo $? 1 neo@matrix:~$ test -z "" neo@matrix:~$ echo $? 0 neo@matrix:~$ test -n "neo" neo@matrix:~$ echo $? 0 neo@matrix:~$ test -n "" neo@matrix:~$ echo $? 1 Acima temos os testes de vazio. A opção "-z" verifica se é vazio, e "-n" se não é vazio. No primeiro caso, ele testa se "neo" é uma string vazia, retornando falso. Já no segundo caso, como "" é vazia, retorna verdadeiro. O terceiro e quarto são semelhantes aos primeiros, mas com "- n". Expressões com arquivos: Os testes que podem ser feitos com arquivos são para verificar determinadas caracteristicas, como se ele existe, se é executavel, se é um link simbólico, se é um diretório etc. Alguns exemplos: A opção "-e" verifica apenas se um arquivo existe e a opção "-d" verifica se o arquivo é um diretório. A opção "-nt" verifica se o primeiro arquivo é mais novo que o segundo (nt = newer than) e "- ot" verifica se o primeiro é mais velho que o segundo (od = older than): neo@matrix:~$ test -e /vmlinuz neo@matrix:~$ echo $? 0 neo@matrix:~$ test -d /vmlinuz neo@matrix:~$ echo $? 1 neo@matrix:~$ test -e /usr neo@matrix:~$ echo $? 0 neo@matrix:~$ test -d /usr neo@matrix:~$ echo $? 0 neo@matrix:~$ test /usr -nt /vmlinuz neo@matrix:~$ echo $? 0 neo@matrix:~$ test /usr -ot /vmlinuz neo@matrix:~$ echo $? 1 A seguir, temos uma lista de várias opções disponíveis: -b arquivo - Verdadeiro se arquivo é um arquivo de bloco, como /dev/hda. -c arquivo - Verdadeiro se arquivo é um arquivo de caracter, como /dev/tty1.
  • 10. -d arquivo - Verdadeiro se arquivo é um diretório. -e arquivo - Verdadeiro se arquivo existe. -f arquivo - Verdadeiro se arquivo existe e é um arquivo comum. -s arquivo - Verdadeiro se arquivo existe e não é vazio. -h arquivo - Verdadeiro se arquivo é um link simbólico. -p arquivo - Verdadeiro se arquivo é um "named pipe" (fifo, lifo, etc). -S arquivo - Verdadeiro se arquivo é um "socket". -k arquivo - Verdadeiro se arquivo tem seu "sticky bit" ligado. -r arquivo - Verdadeiro se arquivo pode ser lido pelo usuário atual. -w arquivo - Verdadeiro se arquivo pode ser escrito pelo usuário atual. -x arquivo - Verdadeiro se arquivo pode ser executado pelo usuário atual. -O arquivo - Verdadeiro se arquivo pertence ao usuário atual. -G arquivo - Verdadeiro se arquivo pertence ao grupo do usuário atual. -N arquivo - Verdadeiro se arquivo foi modificado desde a ultima vez que foi lido. Expressões Aritméticas Expressões aritméticas consistem com comparar dois números, verificando se são iguais, ou se o primeiro é maior que o segundo etc. Infelizmente não podemos apenas utilizar os símbolos conhecidos para igual (=), maior que (>), menor que (<) etc. Temos que usar operadores reconhecidos pelo "test". Assim, não podemos fazer: "test 1 = 1", devemos utilizar o operador "-eq" (equal): "test 1 -eq 1". A seguir, temos uma lista dos operadores: -eq (equal): Igual; -ne (not-equal): Não Igual (diferente); -lt (less than): Menor que (<); -le (less than or equal): Menor ou igual ( <= ); -gt (greater than): Maior que (>); -ge (greater than or equal): Maior ou igual (>=); Alguns exemplos: neo@matrix:~$ test 1 -lt 2 neo@matrix:~$ echo $? 0 neo@matrix:~$ test 1 -gt 2 neo@matrix:~$ echo $? 1 neo@matrix:~$ test 2 -gt 1 neo@matrix:~$ echo $? 0 neo@matrix:~$ test 2 -ge 2 neo@matrix:~$ echo $? 0 Para finalizar, vamos fazer duas considerações. A primeira é de que o comando "test" pode ser substituido por um par de colchetes [ ]. Assim, o comando test "a" = "b" pode ser escrito como [ "a" = "b" ]. Essa segunda nomenclatura fica mais fácil e simples, principalmente quando estamos utilizando IF: if [ -e /vmlinuz ]; é mais intuitivo e simples que if test -e /vmlinuz;.
  • 11. A segunda consideração é que, obviamente, podemos utilizar variáveis no lugar dos argumentos (caso contrário, ficaria difícil utilizar comandos de condicionais em shell script). Assim, se tivermos duas variaveis, valor1=5 e valor2=8: [ "$valor1" = "$valor2" ] , [ "$valor1" -lt "$valor2" ] etc. É importante colocarmos os valores entre aspas duplas ("), pois assim o bash pode substituir o que se encontra dentro dessas aspas. Se colocarmos entre aspas simples ('), impedimos o bash de alterar o que se encontra dentro delas. Se não utilizarmos as aspas duplas, vamos ter problemas, principalmente ao trabalharmos com string. Por exemplo, queremos comparar dois nomes, que se encontram em duas variaveis:nome1="fulano de tal" e nome2="ciclano".Montando nossa expressão condicional: [ "$nome1" = "$nome2" ].O bash irá expandir isso para: [ "fulano de tal" = "ciclano" ], ficando claramente definidos o primeiro e o segundo argumento. Agora, se não usarmos aspas: [ $nome1 = $nome2 ]. O bash irá expandir isso para: [ fulano de tal = ciclano ]. Perceba que os argumentos se misturam e o bash não vai saber o que comparar.Por isso é importante colocarmos os argumentos entre aspas duplas. Conclusão Resumindo, aprendemos na aula de hoje como utilizar comandos condicionais. Isso será fundamental nas proximas aulas, onde iremos tratar os comandos de laço, como o while. Não perca! Curso de Shell - Aula IV Introdução Nesta aula vamos aprender sobre comandos de laço como o while, for, case e select. Eles nos permitem executar alguns comandos diversas vezes, sob determinadas condições e até montar menuzinhos para interagir com o usuário. While Este é provavelmente o comando de laço mais utilizado em programação. Seu entendimento é simples. Ele testa uma condição (como faz o IF) e executa um conjunto de comandos se esta condição for verdadeira. Após a execução desses comandos, ele torna a testar a condição e se esta for verdadeira, ele reexecuta os comandos e assim por diante. Sua sintaxe é a seguinte: while [ condição ]; do comando 1; comando 2; ... done; O parâmetro [ condição ] funciona exatamente igual ao do IF. Não voltarei a abortar os parâmetros condicionais pois eles já foram explicados na aula 3. Em caso de dúvida sobre isso, uma rápida revisão na aula 3 é suficiente. Bom, vamos ao exemplo mais simples do While: um contador. x = 0 While [ "$x" -le 10 ]; do
  • 12. echo "Execução número: $x"?; x = $((x+1)); done; Analisando: Na primeira linha temos a condição: enquanto o valor da variável x ( $x ) for menor-igual ( -le ) a 10, faça: mostre "Execução número: " e o valor de x ($x). Faça x = x + 1. Isso no bash é feito pelo comando $(( )). Ele realiza operações algébricas com variáveis. No caso acima, estamos somando x + 1 e colocando o resultado no próprio x. Preste atenção, que as linhas do While precisam de um ";" para terminar, exceto a que contém o "do", pois ele representa o começo do bloco de comandos. Quando executamos o script acima, temos uma contagem de 1 até 10: neo@matrix:~$ x=0; while [ "$x" -lt 10 ]; do x=$((x+1)); echo "Execução número: $x"; done; Execução número: 1 Execução número: 2 ... Execução número: 10 neo@matrix:~$ O While tem muita utilidade em programação, mas fica difícil dar exemplos usando somente ele, pois geralmente ele está associado a execução de outros programas e rotinas mais complexas. Eu costumo usar ele, por exemplo, quando quero que o napster fique tentando conectar, pois quando ele vai tentar conectar o servidor e não consegue, ele simplesmente termina. Ai eu coloco o while testando a código de retorno dele (lembram da variável $? ) e enquanto estiver diferente de zero (o napster terminou com erro), ele fica executando o napster: ? = 1; while [ "$?" -ne "0" ]; do ./nap; done; O comando "? = 1" tenta atribuir 1 a variável ?. Isso provoca um erro, pois a variável ? É somente de leitura. Isso é necessário para que ? Contenha algo diferente de 0, pois senão o While não executa a primeira interação. For O for é semelhante ao while usado como um contador. É necessário fornecer uma lista de nomes e ele executa os comandos para cada nome na lista. Parece meio confuso, mas é simples. Veja a sintaxe: for <var> in <lista>; do comandos done; O For associa o primeiro item da lista de nomes à variável <var> e executa os comandos. Em seguida, associa novamente o segundo item da lista à <var> e executa novamente os comandos... e assim por diante, até acabar a lista. Veja o exemplo:
  • 13. neo@matrix:~$ for x in Compra Venda Aluguel; do echo $x; done; Compra Venda Aluguel Ou seja, primeiro ele coloca "Compra" na variável x e executa os comandos, no caso, "echo $x", e assim por diante. Podemos facilmente implementar um contador, usando em conjunto com o for, o programinha "seq". Ele simplesmente gera uma seqüência de números. Por exemplo, "seq 10" gera uma seqüência de 1 até 10. Assim, podemos usá-lo no for: for x in $(seq 10); do echo $x; done; Esse comando é semelhante ao contador implementado com o While. Primeiro o x vale 1 e o for executa os comandos. Depois x vale 2 e ele reexecuta os comandos... Vamos usar o For para renomear os arquivo de um diretório, mudando todos os arquivo terminados em ".mp3" para ".mp3.bak". for x in *; do mv "$x" "${x}.bak"; done; for x in *.mp3; do if [ -e "$x" ]; then mv "$x" "${x}.bak"; fi; done; No local de <lista> nos colocamos "*.mp3". Isso diz ao bash para expandir (transformar) ele na lista de arquivos terminados com ".mp3". Senão houver nenhum arquivo com essa terminação, o bash não faz nada, ficando para o for a string "*.mp3". Por isso precisamos do IF para testar se o arquivo existe. Experimente no seu sistema. echo *.mp3 Vai mostrar os arquivos no diretório atual com terminação mp3, mas sem quebra de linha entre eles, ou seja, um nome após o outro. Se não houver nenhum arquivo com terminação mp3, ele apenas vai mostrar "*.mp3". Bom, voltando ao For, ele vai atribuir a "x" cada nome na lista de arquivos com terminação ".mp3" e executar os comandos seguintes. Primeiro ele testa para ver se o arquivo existe ( if [ -e "$x" ]; ), e se existir, renomeia ele para o seu próprio nome acrescido de ".bak" ( ${x}.bak ). Resumindo, o For faz isso: você fornece uma lista de nomes para ele e ele vai atribuindo esses nomes, em ordem e um por vez, à variável <var> e executa os comandos entre o "do" e o "done;".
  • 14. Case O Case está mais para um comando condicional do que para comando de laço, visto que ele não executa "loopings" como o While e o For. Ele geralmente é utilizado como substituição de vários IFs.. Um exemplo clássico e muito utilizado é quando você precisa testar um parâmetro fornecido na linha de comando. O Case é utilizado desta forma em scripts de inicialização de serviços do sistema. Vou mostrar a sintaxe em em seguida um script que inicialize/ reinicialize ou pare algum serviço (como o sendmail, apache, bind, etc). Sintaxe: case <parâmetro> in <opção 1>) <comandos 1> ;; [opção 2]) <comandos 2> ;; * ) <comandos se não for nenhuma das opções> ;; esac Vamos as explicações. O Case pega a string fornecida em <parâmetro> e compara com <opção 1>. Se forem iguais, ele executa <comandos 1> e sai fora. Caso contrario, ele compara <parâmetro> com <opção 2> e assim por diante. Caso <parâmetro> não seja igual a nenhuma das opções, ele executa os comandos da opção "*", se este existir. Prestem atenção a alguns detalhes na sintaxe. Deve existir um ")" após cada opção e também um ";;" após todos os comandos de cada opção. Vejam o exemplo abaixo: case "$1" in 'start' ) echo "Iniciando o serviço..." <comandos para iniciar o serviço> ;; 'restart' ) echo "Reinicializando o serviço..." <comandos para reinicializar o serviço> ;; 'stop' ) echo "Parando o serviço..." <comandos para parar o serviço> ;; *) echo "Opção invalida!" echo "As opções válidas são: start, stop e restart" ;; esac O Case serve exatamente para isso, ou seja, evitar o teste de vários Ifs. No caso acima, teríamos que utilizar 3 Ifs. Mesmo se o primeiro já fosse verdadeiro, o bash iria testar o segundo e o terceiro, ou seja, ia perder tempo desnecessariamente. Já no case isso não acontece. Após entrar em uma opção e executar seus comandos, ele já pula fora do case sem testar as outras opções abaixo. Select O Select é um comando de laço que nos permite mostrar um pequeno menuzinho de opções
  • 15. para o usuário. Cada opção possui um número e para escolher, o usuário digita o número correspondente a opção desejada. Vejamos a sintaxe a seguir: select <var> in <lista de opções>; do <comandos> done; Como disse acima, o select vai mostrar as opções contidas em <lista de opções>, uma por linha, com um número na frente e espera que o usuário digite a opção desejada. Ao digitar a opção, o select atribui o nome da opção a variável <var> e executa os comandos. Para sair do select, é necessário executar o comando "break". Vamos a um exemplo: select x in Iniciar Reiniciar Parar Sair; do echo "Opção Escolhida: $x" if [ "$x" == "Sair" ]; then break; fi; done; Ou seja, se o usuário escolher alguma opção diferente de "Sair", o script apenas escreve a opção. Se for escolhida Sair, ele mostra a opção, entra no IF e executa o break, saindo do select. É interessante combinar o Select com o Case. Vamos mostrar como ficaria aquele exemplo do case, de iniciar um serviço, utilizando o Select, para tornar o script interativo: select x in Iniciar Reiniciar Parar Sair; do case "$x" in 'Iniciar' ) echo "Iniciando o serviço..." ;; 'Reiniciar' ) echo "Reinicializando o serviço..." ;; 'Parar' ) echo "Parando o serviço..." ;; 'Sair' ) echo "Script encerrado." break ;; *) echo "Opção inválida!" ;; esac done; Primeiramente o Select mostra um menuzinho: 1) Iniciar 2) Reiniciar 3) Parar 4) Sair #? Quando o usuário digitar um número de opção, o select executa o case e este compara a variável x com suas opções. Se achar alguma, executa seus comandos, no caso um echo. Se o usuário escolher Sair, além do echo, ele executa o "break", que interrompe o select: neo@matrix:~/test$ ./t 1) Iniciar 2) Reiniciar 3) Parar 4) Sair #? 1 Iniciando o serviço... 1) Iniciar
  • 16. 2) Reiniciar 3) Parar 4) Sair #? 5 Opção inválida! 1) Iniciar 2) Reiniciar 3) Parar 4) Sair #? 4 Script encerrado. neo@matrix:~/test$ Bom pessoal, acho que por hoje é só. ;-) Espero que vocês tenham pego a idéia de como funciona comandos de laços. Pelos menos sabendo a utilidade, sintaxe e como funcionam, quando surgir a necessidade, vocês já vão saber quais ferramentas usar. Qualquer dúvida, sugestão, etc, podem me enviar um e-mail. Terei o maior prazer em responder. Até a próxima aula! Curso de Shell - Aula V Introdução Nesta aula teremos um breve tutorial sobre o Grep. Ele não é somente um dos comandos mais úteis, mas o seu domínio abre portas para dominar outros poderosos comandos, como o sed (que trataremos na próxima aula), awk, perl, etc. Eu fiz uma adaptação/modificação de um tutorial que eu tenho, e por sinal é excelente, sobre o Grep e Expressões Regulares em inglês. Espero que tenha ficado legal e vocês gostem. O que ele faz? O grep basicamente faz buscas. Mais precisamente: grep <palavra> <file> Retorna todas as linhas do arquivo <file> que contenham <palavra> Outro jeito de usar o grep é atraves de pipe (lembram dos pipes?). Por exemplo: ls | grep <palavra> Lista todos os arquivos que contenham <palavra> em seu nome. Ou seja, a entrada do grep é uma lista de arquivos (gerada pelo ls) que será filtrada, sendo impressas somente as linhas que contenham <palavra>. Usando caracteres coringas Suponho que todos saibam o que são caracteres coringas. Caso contrário, coringas são caracteres especiais que substituem outros. Geralmente o caracter "*" é um coringa que significa "qualquer caracter em qualquer quantidade". Por isso se a gente executar "ls *", onde "*" entra no lugar do "nome do arquivo", significando qualquer string de qualquer tamanho. Por isso ele lista todos os arquivos. Mas agora voltemos ao grep. Será que ele aceita coringas ??? A resposta é mais do que sim. O grep suporta algo que vai além de coringas, ele suporta Expressões Regulares. Mas vamos começar apenas com coringas. Um dos mais usados com o grep é o "." Vamos a um exemplo:
  • 17. >cat file file big bad bug bigger boogy >grep b.g big bad bug bigger Note que boogy não casa, desde que "." significa "qualquer e apenas um caracter". Para significar strings arbitrárias utilizamos "*", que funciona da seguinte maneira: "A expressão consistindo de um caracter seguido por um * casa com qualquer número (inclusive zero) de repetições desse caracter. Em particular, ".*" significa qualquer string." Para compreendermos vamos a mais exemplos: >cat file big bad bug bag bigger boogy >grep b.*g file big bad bug bag bigger boogy >grep b.*g. file bigger boogy >grep ggg* file bigger Avançando para expressões regulares Os coringas são o começo, mas a idéia vai mais longe. Por exemplo, suponha que queremos uma expressão que case com Frederic Smith ou Fred Smith, ou seja, a string "eric" é opcional. Primeiro, introduzimos o conceito de um "caracter escapado (escaped character)". "Um caracter escapado é um caracter precedido por uma barra invertida ( ). Essa barra invertida faz o seguinte: (a) Remove qualquer significado especial do caracter. (b) acrescenta um significado especial a um caracter que não tenha um significado especial." Parece complicado, mas veja nos exemplo que é um tanto quanto simples: Para procurar uma linha contento o texto "hello.gif", o comando correto seria: grep 'hello.gif' file
  • 18. Desde que "grep 'hello.gif' file" iria resultar linhas contendo: hello-gif , hello1gif , helloagif , etc. Ou seja, a barra invertida remove o significado especial do ".", passando esse a significar um simples ponto ao invés de um coringa. Agora vamos passar para expressões agrupadas, a fim de encontrar um jeito de criar uma expressão que case com Frederic ou Fred. Primeiro vamos começar com o operador "?": "Uma expressão consistindo de caracter seguido por uma interrogação escapada ( ? ) casa com zero ou uma instância daquele caracter". Exemplo: "bugg?y" casa com o seguinte: bugy , buggy mas não com bugggy neo@matrix:~$ echo bugy | grep "bugg?y" bugy neo@matrix:~$ echo bugggy | grep "bugg?y" neo@matrix:~$ Agora vamos para expressões agrupadas. No nosso exemplo, queremos tornar opcional a string "eric" após "Fred", ou seja, não apenas um caracter mas sim um conjunto de caracteres (string). "Uma expressão dentro de parênteses escapados é tratada como um único caracter" Exemplos: "Fred(eric)?" Smith casa com "Fred Smith" or "Frederic Smith" (abc)* casa com abc , abcabcabc, etc (isto é, qualquer número de repetições da string "abc", incluindo zero). Note que temos que tomar cuidado quando nossas expressões contém espaços em branco. Quando eles aparecem, precisamos colocar a expressão entre aspas, para que o shell não interprete mal nosso comando. Para o exemplo acima: grep "Fred(eric)? Smith" file Eu aconselho fortemente a sempre usar aspas, mesmo que não usemos espaços em brancos. Já tive muita dor de cabeça porque expressões e comandos não funcionavam simplesmente por não estarem entre aspas. Um dos exemplo acima (o do bugg?y) não funciona no meu sistema se não estiver entre aspas. Veja: neo@matrix:~$ echo bugy | grep "bugg?y" bugy neo@matrix:~$ echo bugy | grep bugg?y neo@matrix:~$ Outros operadores úteis Para casar algum caracter de uma lista, use [ ] Veja: "[Hh]ello" casa com linhas contendo "hello" ou "Hello" Faixas de caracteres também são permitidos: [0-3] é o mesmo que [0123] [a-k] é o mesmo que [abcdefghijk]
  • 19. [A-C] é o mesmo que [ABC] [A-Ca-k] é o mesmo que [ABCabcdefghijk] Existem também algumas formas alternativas: [[:alpha:]] é o mesmo que [a-zA-Z] [[:upper:]] é o mesmo que [A-Z] [[:lower:]] é o mesmo que [a-z] [[:digit:]] é o mesmo que [0-9] [[:alnum:]] é o mesmo que [0-9a-zA-Z] [[:space:]] casa com qualquer quantidade de espaços, inclusive tabulações Essas formas alternativas, como [[:digit:]] é preferível ao método direto, [0-9]. Os [ ] podem ser usado para indicar caracteres que NÃO devem estar na expressão. É só colocar o sinal ^ na primeira posição da lista. Veja: neo@matrix:~$ echo hello | grep "[Hh]ello" hello neo@matrix:~$ echo hello | grep "[^Hh]ello" neo@matrix Outro exemplo, um pouco mais complicado: grep "([^()]*)a" file (hello)a (aksjdhaksj d ka)a Retorna qualquer linha contendo um par de parentes seguido por "a" e que NÃO contenham outros parênteses dentro. Mas não com: x=(y+2(x+1))a Casando com um número especifico de repetições Suponha que você queira casar um número específico de repetições de uma expressão. Um bom exemplo são números de telefones. Você pode procurar por um número de telefone com sete dígitos, assim: grep "[:digit:]{3}[ -]?[:digit:]{4}" file Ou seja, três dígitos, opcionalmente um espaço ou um hífen e mais 4 dígitos. Procurando por começo e fim de linha: Isso é muito interessante. Digamos que você queira procurar por linhas que contendo espaços em brancos no começo da linha, a palavra hello e então o fim da linha. Vamos começar com este exemplo: >cat file hello hello world hhello >grep hello file
  • 20. hello hello world hhello Isso não é o que nós queremos. O que está errado ? O problema é que o grep procura por linhas contendo a string hello e todas as linhas especificadas contem ela. Para contornar isso, introduzimos os caracteres de começo e fim de linha: "O caracter ^ significa começo de linha e o $ significa fim da linha" Retornando ao nosso exemplo: grep "^[[:space:]]*hello[[:space:]]*$" file Ou seja, o começo da linha, qualquer quantidade de espaço em branco (inclusive zero), a palavra hello, qualquer quantidade de espaço em branco e o fim da linha. Essa expressão faz o que a gente quer, retornando somente a linha que contém a palavra hello. Outro exemplo: grep "^From.*Alex" /var/spool/mail/neo Procura no meu inbox por mensagens de uma pessoa em particular (no caso, Alex). Esse tipo de expressão regular é extremamente útil e filtros de e-mail, como o procmail, utilizam isso para fazerem tudo. Isso ou Aquilo: Procurando uma coisa OU outra: "A expressão consistindo de duas expressões separadas pelo operador OU | casa linhas contendo uma das duas expressões" Note que você DEVE colocar a expressão dentro de aspas simples ou duplas: grep "cat|dog" file casa com linhas contendo a palavra "cat" ou a palavra "dog" grep "I am a (cat|dog)" casa com linhas contendo a string "I am a cat" ou a string "I am a dog". Usando backreference (referencia anterior) Digamos que você queira procurar strings que contenham uma substring em mais de um lugar. Um exemplo é as tags de cabeçalhos de HTML. Suponha que eu queira procurar por "<H1>alguma string</H1>". Isto é fácil de se fazer. Mas suponha que eu queira fazer o mesmo, mas permita H2 H3 H4 H5 e H6 no lugar de H1. A expressão .* não é boa, desde que casa com "<H1>alguma string</H3>" e nos queremos que a tag de abertura seja igual a de fechamento. Para fazermos isso, usamos backreference: "A expressão n onde n é um número, casa com o conteúdo do n-ésimo conjunto de parênteses na expressão". Nossa... isso realmente precisa de um exemplo!!!! .* faz o que nos queríamos fazer acima... "O Senhor (dog|cat) e a senhora 1 foram visitar o Senhor (dog| cat) e a senhora 2" Esse é outro exemplo bobo. Os casais tem sempre que serem iguais. Ou um casal de cachorro ou de gato.
  • 21. Alguns detalhes cruciais: caracteres especiais e aspas Caracteres Especiais: Aqui nós descrevemos os caracteres especiais para RegExp (expressões regulares) no grep. Note que no "egrep", que usa expressões regulares estendidas (atualmente não tem nenhuma funcionalidade a mais que as expressões regulares normais do GNU grep), a lista de caracteres especiais são os mesmos, diferindo somente que alguns não precisar estar "escapados". Os seguintes caracteres são considerados especiais, e precisam estar escapados: ? . [ ] ^ $ Note que o sinal de $ perde seu sentido se tiver caracteres depois dele, do mesmo jeito que o sinal ^ perde seu sentido se tiver caracteres antes dele. Os colchetes [ ] comportam-se um pouco diferente. A baixo segue as regras para eles: - O colchete direito ( ] ) perde seu sentido especial se colocado no começo de uma lista, por exemplo: "[]12]" casa com ] , 1, or 2. - Um hífen perde seu significado especial se colocado por último. Assim, [15-] casa com 1, 5 ou - - O caracter ^ perde seu sentido se não for colocado em primeiro lugar. - A maioria dos caracteres especiais perdem seu significado especial se forem colocados dentro de colchetes. Aspas: Em primeiro lugar, aspas simples são mais seguras de usar porque elas protegem suas expressões regulares de serem alteradas pelo bash (como foi visto nas aulas anteriores). Por exemplo, grep "!" file vai produzir um erro, já que o shell pensa que "!" está se referindo ao comando de histórico do shell, enquanto grep '!' file funciona perfeitamente. Quando você deve usar aspas simples ? A resposta é: se você precisa usar variáveis do shell, use aspas duplas. Caso contrário, use aspas simples. Por exemplo: grep "$HOME" file Procura em file pelo nome do seu diretório pessoal, enquanto grep '$HOME' file procura pela string $HOME. Sintaxe das expressões regulares estendidas Agora vamos ver a sintaxe do egrep em contraste com a sintaxe do grep. Ironicamente, apesar do nome "estendido", o egrep atualmente tem menos funcionalidade do que quando foi criado, para manter a compatibilidade com o tradicional grep. A melhor maneira de fazer um grep estendido é utilizar grep -E que usa a sintaxe de expressões regulares estendidas sem perda de funcionalidade. Bom, espero que vocês tenham tido uma boa idéia de como funcionam as expressões regulares. Elas são extremamente importante, principalmente para utilizar o grep e o poderosíssimo sed, do qual trataremos na próxima aula. Não se preocupem se estiverem confuso com as expressões, quando começarem a utilizá-las, as idéias vão clareando. Até a próxima. Curso de Shell - Aula VI Introdução Nesta aula continuaremos nosso tutorial, desta vez falando sobre o Sed. Vale lembrar que este tutorial dará uma breve introdução ao Sed, ajudando os iniciantes a entender como ele funciona. Portanto muitos comandos mais complexos serão omitidos, já que seria necessário um livro inteiro para ensinar tudo sobre o Sed. Mas não se preocupem, ensinaremos o suficiente sobre ele para utilização em shell script.
  • 22. Resumo de RegExp Vamos a um resumo sobre as expressões regulares, explicadas na aula anterior e agora aplicadas ao Sed: ^ casa com o começo de linha $ casa com o fim de linha . casa com qualquer caracter simples (apenas um) (caracter)* casa com qualquer ocorrência, em qualquer quantidade, de (caracter) (caracter)? casa com zero ou uma ocorrência de (caracter) [abcdef] casa com qualquer caracter dentro dos [ ] (neste caso, a b c d e ou f), faixas de caracteres como [a-z] são permitidas. [^abcdef] casa com qualquer caracter NÃO incluído em [] (neste caso, qualquer caracter que não seja a b c d e ou f) (caracter){m,n} casa com m-n repetições de (caracter) (caracter){m,} casa com m ou mais repetições de (caracter) (caracter){,n} casa com n ou menos (também zero) repetições de (caracter) (caracter){n} casa com exatamente n repetições de (caracter) (expressão) operador de grupo. n backreference - casa com o n- ésimo grupo expressão1|expressão2 casa com expressão1 ou expressão2. Funciona com o GNU sed, mas essa característica pode não funcionar com outros Seds. Caracteres Especiais Os caracteres especiais no Sed são os mesmo do Grep, com uma diferença: a barra normal / é um caracter especial no sed. A razão disso ficará clara mais para frente quando estudarmos os comandos do sed. Como funciona: Uma breve introdução O Sed funciona assim: ele lê da entrada padrão, uma linha de cada vez. Para cada linha, ele executa uma série de comandos de edição e então a linha é escrita na saída padrão. Um exemplo que mostra como ele funciona: Nós usamos o comando "s", que significa "substitute" (substituir) ou "search and replace" (procurar e trocar). O formato é: s/expressão-regular/texto-substituto/{flags} Nós não vamos discutir todas as flags ainda. A única que usamos abaixo é a "g", que significa "substitua todas as ocorrências": >cat file Eu tenho três cachorros e dois gatos >sed -e 's/cachorros/gatos/g' -e 's/gatos/elefantes/g' file Eu tenho três elefantes e dois elefantes OK, então o que aconteceu? Primeiro o sed leu a linha do arquivo "file" e executou: s/cachorros/gatos/g que produziu o seguinte texto: Eu tenho três gatos e dois gatos
  • 23. e então o segundo comando foi executado na linha já editada e resultou: Eu tenho três elefantes e dois elefantes Nós atualmente damos um nome para o texto (geralmente uma linha) que o sed leu e está processando (editando): ele chama-se "pattern space" (uma boa tradução seria "área de edição"). O sed lê da entrada padrão e joga na sua área de edição, executando nela uma seqüência de comandos de edição e então ele escreve o resultado na saída padrão. Comandos de Substituição e Deleção Primeiro, as maneiras mais usuais do sed é a seguinte: >sed -e 'comando1' -e 'comando2' -e 'comando3' arquivo >{comando shell} | sed -e 'comando1' -e 'comando2' >sed -f sedscript.sed arquivo >{comando shell} | sed -f sedscript.sed Então, o sed pode ler do arquivo ou da entrada padrão, e os comandos podem ser especificados em um arquivo de script ou na linha de comando. Esse arquivo, chamado sedscript.sed é um arquivo que contém todos os comandos do sed, ao invés de serem especificados na linha de comando. Esses sed's scripts são úteis quando precisamos de um processamento de texto mais complexo e refinado. Note o seguinte: se os comandos são lidos de um arquivo (sed script), espaços em branco podem ser fatais. Eles podem fazer o script falhar sem explicação aparente. Eu recomendo editar os arquivos de comandos do sed com um editor como o VIM que pode mostrar o final da linha e você pode ver se existem espaços em branco entre os comandos e o fim da linha. Comando de Substituição O formato para o comando de substituição é o seguinte: [endereço1[,endereço2]]s/procura/substituto/[flags] As flags podem ser as seguintes: n - troca a n-ésima ocorrência (na linha) do texto "procura" por "substituto" g - troca todas as ocorrências (na linha) do texto "procura" por "substituto" p - imprime a "área de edição" para a saída padrão se ocorrer uma substituição com sucesso w arquivo - imprime a "área de edição" para arquivo se ocorrer uma substituição com sucesso Se nenhuma flag for especificada, somente a primeira ocorrências na linha é substituída. Note que nós quase sempre usamos o comando "s" ou com a flag "g" ou sem nenhuma flag. Se um endereço é dado, então a substituição é aplicada a linhas que contenham aquele endereço. Um endereço pode ser ou uma expressão regular dentro de barras normais /regexp/ , ou um número de linha. O símbolo $ pode ser usado no lugar do número da linha para denotar a última linha. Se dois endereços são fornecidos, separados por uma vírgula, então a substituição é aplicada a todas as linhas entre duas linhas que casam com os endereços fornecidos.
  • 24. Isto requer algum esclarecimento. Mais precisamente, a substituição ocorre em todas as linhas desde a primeira ocorrência de "endereço1" até a primeira ocorrência de "endereço2". Não se preocupe se isso tudo parece meio confuso. Os exemplos vão esclarecer melhor. O comando de Deleção A sintaxe desse comando é muito simples. Ai vai: [endereço1[,endereço2]]d Isto deleta o conteúdo da "área de edição" (se esta casar com os endereços fornecidos). Todos os comandos seguintes serão pulados (já que não a nada a fazer com uma área de edição em branco) e uma nova linha será lida e jogada na área de edição e todo o processo se repete. Exemplos: Exemplo 1: >cat file O gato preto foi caçado por um cachorro marrom. >sed -e 's/preto/branco/g' file O gato branco foi caçado por um cachorro marrom. Exemplo 2: >cat file O gato preto foi caçado por um cachorro marrom. O gato preto não foi caçado por um cachorro marrom. >sed -e '/não/s/preto/branco/g' file O gato preto foi caçado por um cachorro marrom. O gato branco não caçado por um cachorro marrom. Neste caso, a substituição é aplicada somente a linhas que casam com a expressão regular "/não/". Portanto, ela não é aplicada a primeira linha, pois esta não contem a palavra "não". Exemplo 3: >cat file linha 1 (um) linha 2 (dois) linha 3 (três) Exemplo 3a: >sed -e '1,2d' file linha 3 (três) Exemplo 3b: >sed -e '3d' file linha 1 (um) linha 2 (dois) Exemplo 3c:
  • 25. >sed -e '1,2s/linha/LINHA/' file LINHA 1 (um) LINHA 2 (dois) linha 3 (três) Exemplo 3d: >sed -e '/^linha.*um/s/linha/LINHA/' -e '/linha/d' file LINHA 1 (um) 3a : Este foi bem simples: Nós apenas deletamos as linhas de 1 até 2 3b : Isto também foi simples: Nós deletamos a linha 3. 3c : Neste exemplo, nós fizemos uma substituição nas linhas 1 até 2. 3d : Agora este é mais interessante e merece algumas explicações. O primeiro comando vai procurar "^linha.*um" e substituir "linha" por "LINHA", ou seja, somente a primeira linha casa com essa expressão regular. O segundo comando diz para o sed deletar linhas que contenham a palavra "linha". Assim, somente as duas últimas linhas serão deletadas, já que a primeira teve palavra "linha" substituída por "LINHA". Exemplo 4: >cat file olá Este texto será cortado olá (também será retirado) ReTiRaDo Também!!! tchau (1) Este texto não foi apagado (2) nem este ... ( tchau ) (3) nem este olá mas este será e este também e a menos que nós encontremos outro tch*u cada linha até o final do texto será apagada >sed -e '/olá/,/tchau/d' file (1) Este texto não foi apagado (2) nem este ... ( tchau ) (3) nem este Isto mostra como o endereçamento funciona quando dois endereços são especificados. O sed encontra o primeiro casamento da expressão "olá" e deleta todas as linhas lidas na área de edição até ele encontrar a primeira linha que contém a expressão "tchau" (está também será apagada). Ele não aplica mais o comando de deleção para nenhuma linha até encontrar novamente a expressão "olá". Desde que a expressão "tchau" não ocorre mais em nenhuma linha subseqüente, o comando de deleção é aplicado até o final do texto. Resumindo, é simples: Quando ele encontra o primeiro endereço ("olá") ele passa a executar os comandos até encontrar o segundo endereço ("tchau") ou o fim do texto. E isso se repete até acabar o texto. Exemplo 5: >cat file http://www.kernel.org/
  • 26. >sed -e 's@http://www.kernel.org@http://www.metalab.unc.edu@' file http://www.metalab.unc.edu/ Note que nós usamos um delimitador diferente, @ para o comando de substituição. O Sed permite diversos delimitadores para o comando de substituição, incluindo @ % , ; : Esses delimitadores alternativos são bons para substituições que incluem string como nome de arquivos e outras que contém barra normal /, o que torna o código do sed muito mais legível. Mais alguns comandos Aqui veremos mais alguns comandos sobre o sed, a maioria deles mais complexos. Dependendo da aplicação em que vocês forem usar o sed, dificilmente usarão esses recursos, a menos que precisem de um processamento de texto mais refinado e complexo. Veja que eles são muito usado nos scripts do sed (não confunda com shell-script). Backreference no Sed: Uma das coisas legais sobre backreference no sed é que você pode usar não apenas em procura de textos mas também na substituição de textos. O comando Quit: O comando quit ou "q" é muito simples. Ele simplesmente termina o processamento. Nenhuma outra linha é lida para a área de edição ou impressa na saída padrão. Sub-rotinas: Nós agora introduzimos o conceito de sub- rotinas no sed: No sed, as chaves { } são usadas para agrupar comandos. Elas são usadas dessa maneira: endereço1[,endereço2]{ comandos} Exemplo: Encontrar uma palavra de uma lista num arquivo Este exemplo faz um bom uso dos conceitos descritos acima. Para isto, nos usamos um shell-script, desde que os comandos são muito longos e precisaríamos escrever a longa string X várias vezes. Note que usamos aspas duplas, já que a variável $X precisa ser expandida pelo shell. A sintaxe para rodar esse script é: "script arquivo", onde "script" é o nome dado ao script e "arquivo" é o nome do arquivo a procurar uma palavra da lista. #!/bin/sh X='word1|word2|word3|word4|word5' sed -e " /$X/!d /$X/{ s/($X).*/1/ s/.*($X)/1/ q }" $1 Uma nota importante: é tentador pensar que: s/($X).*/1/ s/.*($X)/1/ é redundante e tentar encurta-la para: s/.*($X).*/1/ Mas isto não funciona. Por que? Suponha que temos a linha:
  • 27. word1 word2 word3 Nós não temos como saber se $X vai casar com word1, word2 ou word3, então quando nós citamos ele (1), nós não sabemos quais dos termos está sendo citado. O que está sendo usado para certificar-se que não há problemas na correta implementação, é isto: "O operador * é guloso. Ou seja, quando há ambigüidade sobre qual (expressão)* pode casar, ele tentar casar o máximo possível." Então neste exemplo, s/($X).*/1/ , .* tenta engolir o máximo da linha possível, em particular, se a linha contém isso: "word1 word2 word3" Então nós podemos ter certeza que .* casa com " word2 word3" e portanto $X seria word1. Não se preocupem se não entenderam muito bem este tópico. Ele é complicado mesmo e pouco usado. O importante é entender como ele funciona, o uso de regexp e do comando de substituição e deleção. Para maiores informações sobre o sed, dê uma olhada na sua man page: "man sed" Espero que vocês tenham gostado desse pequeno tutorial sobre sed. Como disse na aula anterior sobre o Grip, é praticando que se aprende a usa-lo. O fim... Bom pessoal, acho que nosso curso termina por aqui. Claro que não deu pra cobrir tudo sobre shell script, se não nosso curso não teria fim. Tentei abordar os topicos mais importantes, de modo que vcs tenham uma boa noção de como funciona as coisas no shell e possam dar os proprios passos. Desculpem se esqueci de falar sobre alguma coisa que vocês estavam esperando. Como disse, estou a disposição para resolver qualquer dúvidas.