Você não aguenta mais aquele seu amigo usuário de Linux enchendo o seu saco com aquela história de que o sistema é fantástico e o Shell é uma ferramenta maravilhosa? A partir desta edição vai ficar mais fácil entender o porquê deste entusiasmo...
1. Linux User Papo de Botequim
Papo de Botequim
Curso de Shell Script
Parte X
Dave Hamilton - www.sxc.hu
Em mais um capítulo de nossa saga através do mundo do
Shell Script, vamos aprender a avaliar expressões, capturar
sinais e receber parâmetros através da linha de comando.
por Júlio Cezar Neves
E
aê amigo, te dei a maior moleza na a legibilidade do código está “horrorível”, O comando eval
última aula né? Um exerciciozinho mas o desempenho, isto é, a velocidade Vou te dar um problema que eu duvido
muito simples… de execução, está ótimo. Como funções que você resolva:
– É, mas nos testes que eu fi z, e de são coisas muito pessoais, já que cada
acordo com o que você ensinou sobre um usa as suas e quase não há neces- $ var1=3
substituição de parâmetros, achei que sidade de manutenção, eu sempre opto $ var2=var1
deveria fazer algumas alterações nas fun- pelo desempenho.
ções que desenvolvemos para torná-las de Hoje vamos sair daquela chatura que Te dei essas duas variáveis e quero que
uso geral, como você disse que todas as foi o nosso último papo e voltar à lógica, você me diga como eu posso, me referindo
funções deveriam ser. Quer ver? saindo da decoreba. Mas volto a te lem- apenas à variável a var2, listar o valor de
– Claro, né, mané, se te pedi para fazer brar: tudo que eu te mostrei da última vez var1 (que, no nosso caso, é 3).
é porque estou a fi m de te ver aprender, aqui no Boteco do Chico é válido e quebra – Ah, isso é mole, mole! É só digitar
mas peraí, dá um tempo. Chico! Manda um galhão. Guarde aqueles guardanapos esse comando aqui:
dois, um sem colarinho! Vai, mostra aí que rabiscamos porque, mais cedo ou
o que você fez. mais tarde, eles lhe vão ser muito úteis. echo $`echo $var2`
– Bem, além do que você pediu, eu
reparei que o programa que chamava a Listagem 1: função pergunta.func
função teria de ter previamente defi nidas 01 # A função recebe 3 parâmetros na seguinte ordem:
a linha em que seria mostrada a mensa- 02 # $1 - Mensagem a ser mostrada na tela
gem e a quantidade de colunas. O que 03 # $2 - Valor a ser aceito com resposta padrão
fi z foi incluir duas linhas – nas quais 04 # $3 - O outro valor aceito
empreguei substituição de parâmetros 05 # Supondo que $1=Aceita?, $2=s e $3=n, a linha
– para que, caso uma dessas variáveis não 06 # abaixo colocaria em Msg o valor "Aceita? (S/n)"
07 TotCols=${TotCols:-$(tput cols)} # Se não estava definido, agora está
fosse informada, ela recebesse um valor
08 LinhaMesg=${LinhaMesg:-$(($(tput lines)-3))} # Idem
atribuído pela própria função. A linha
09 Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)"
de mensagem é três linhas antes do fi m 10 TamMsg=${#Msg}
da tela e o total de colunas é obtido pelo 11 Col=$(((TotCols - TamMsg) / 2)) # Para centralizar Msg na linha
comando tput cols. Dê uma olhada na 12 tput cup $LinhaMesg $Col
listagem 1 e veja como ficou: 13 read -n1 -p "$Msg " SN
– Gostei, você já se antecipou ao que eu 14 SN=${SN:-$2} # Se vazia coloca o padrão em SN
ia pedir. Só pra gente encerrar esse papo 15 SN=$(echo $SN | tr A-Z a-z) # A saída de SN será em minúsculas
16 tput cup $LinhaMesg $Col; tput el # Apaga Msg da tela
de substituição de parâmetros, repare que
86 julho 2005 edição 10
www.linuxmagazine.com.br
2. Papo de Botequim Linux User
Repare que eu coloquei o echo $var2 entre crases (`), porque $ var2=ls
dessa forma ele terá prioridade de execução e resultará em var1. $ $var2
E echo $var1 produzirá 3… 10porpag1.sh alo2.sh incusu logado
– Ah, é? Então execute para ver se está correto. 10porpag2.sh ArqDoDOS.txt1 listamusica logaute.sh
10porpag3.sh confuso listartista mandamsg.func
$ echo $`echo $var2` alo1.sh contpal.sh listartista3 monbg.sh
$var1
Agora vamos colocar em var2 o seguinte: ls $var1; e em
– Ué! Que foi que aconteceu? O meu raciocínio me parecia var1 vamos colocar l*, vejamos o resultado:
bastante lógico…
– O seu raciocínio realmente foi lógico, o problema é que você $ var2='ls $var1'
esqueceu de uma das primeiras coisas de que te falei aqui no $ var1='l*'
Boteco e que vou repetir. O Shell usa a seguinte ordem para $ $var2
resolver uma linha de comando: ls: $var1: No such file or directory
P Resolve os redirecionamentos; $ eval $var2
P Substitui as variáveis pelos seus valores; listamusica listartista listartista3 logado logaute.sh
P Resolve e substitui os meta caracteres;
P Passa a linha já toda esmiuçada para execução. Novamente, no tempo de substituição das variáveis, $var1
Dessa forma, quando o interpretador chegou na fase de re- ainda não havia se apresentado ao Shell para ser resolvida.
solução de variáveis, que como eu disse é anterior à execução, Assim, só nos resta executar o comando eval para dar as duas
a única variável existente era var2 e por isso a tua solução passadas necessárias.
produziu como saída $var1. O comando echo identificou isso Uma vez um colega da excelente lista de discussão groups.yahoo.com/
como uma cadeia de caracteres e não como uma variável. group/shell-script colocou uma dúvida: queria fazer um menu
Problemas desse tipo são relativamente freqüentes e seriam que numerasse e listasse todos os arquivos com extensão .sh e,
insolúveis caso não existisse a instrução eval, cuja sintaxe é quando o operador escolhesse uma opção, o programa corres-
eval cmd, onde cmd é uma linha de comando qualquer, que pondente fosse executado. Veja minha proposta na listagem 2:
você poderia inclusive executar direto no prompt do terminal.
Quando você põe o eval na frente, no entanto, o que ocorre é Listagem 2: fazmenu.sh
que o Shell trata cmd como um parâmetro do eval e, em seguida, 01 #!/bin/bash
o eval executa a linha recebida, submetendo-a ao Shell. Ou 02 #
seja, na prática cmd é analisado duas vezes. Dessa forma, se 03 # Lista que enumera os programas com extensão .sh no
executássemos o comando que você propôs colocando o eval 04 # diretório corrente e executa o escolhido pelo operador
05 #
na frente, teríamos a saída esperada. Veja:
06 clear; i=1
07 printf "%11st%snn" Opção Programa
$ eval echo $`echo $var2` 08 CASE='case $opt in'
3 09 for arq in *.sh
10 do
Esse exemplo também poderia ter sido feito de outra maneira. 11 printf "t%03dt%sn" $i $arq
12 CASE="$CASE
Dá só uma olhada:
13 "$(printf "%03d)t %s;;" $i $arq)
14 i=$((i+1))
$ eval echo $$var2 15 done
3 16 CASE="$CASE
17 *) . erro;;
Na primeira passada a contrabarra () seria retirada e $var2 18 esac"
19 read -n3 -p "Informe a opção desejada: " opt
seria resolvido produzindo var1. Na segunda passada teria so-
20 echo
brado echo $var1, que produziria o resultado esperado. Agora 21 eval "$CASE"
vou colocar um comando dentro de var2 e executar:
julho 2005 edição 10 87
www.linuxmagazine.com.br
3. Linux User Papo de Botequim
Parece complicado porque usei muitos dos por) processos em execução. Vamos, "limpar a área" ao seu término. Se seu
printf para formatação da tela, mas na de agora em diante, dar uma olhadinha encerramento ocorrer de forma prevista,
verdade é bastante simples: o primei- nos sinais enviados aos processos e mais ou seja, se tiver um término normal, é
ro printf foi colocado para imprimir à frente vamos dar uma passada rápida muito fácil fazer essa limpeza; porém,
o cabeçalho e logo em seguida come- pelos sinais gerados pelos processos. se o seu programa tiver um fim brusco,
cei a montar dinamicamente a variável Para mandar um sinal a um processo, muita coisa ruim pode ocorrer:
$CASE, na qual ao final será feito um eval usamos normalmente o comando kill, P É possível que em um determinado es-
para execução do programa escolhido. cuja sintaxe é: paço de tempo, o seu computador esteja
Repare no entanto que dentro do loop cheio de arquivos de trabalho inúteis
do for existem dois printf: o primeiro $ kill -sig PID P Seu processador poderá ficar atolado
serve para formatar a tela e o segundo de processos zombies e defuncts gera-
para montar o case (se antes do coman- Onde PID é o identificador do proces- dos por processos filhos que perderam
do read você colocar uma linha echo so (Process Identification ou Process ID). os pais e estão “órfãos”;
"$CASE", verá que o comando case mon- Além do comando kill, algumas seqüên- P É necessário liberar sockets abertos para
tado dentro da variável está todo inden- cias de teclas também podem gerar sinais. não deixar os clientes congelados;
tado. Frescura, né?:). Na saída do for, foi A tabela 1 mostra os sinais mais impor- P Seus bancos de dados poderão ficar
adicionada uma linha à variável $CASE tantes para monitorarmos: corrompidos porque sistemas gerencia-
para, no caso de uma escolha inválida, Além desses, existe o famigerado si- dores de bancos de dados necessitam
ser executada uma função externa para nal -9 ou SIGKILL que, para o processo de um tempo para gravar seus buffers
exibir mensagens de erro. Vamos execu- que o está recebendo, equivale a meter em disco (commit).
tar o script para ver a saída gerada: o dedo no botão de desligar do compu- Enfim, existem mil razões para não usar
tador – o que é altamente indesejável, um kill com o sinal -9 e para monitorar o
$ fazmenu.sh já que muitos programas necessitam encerramento anormal de programas.
Opcao Programa
Listagem 3: Nova versão do fazmenu.sh
001 10porpag1.sh
01 #!/bin/bash
002 10porpag2.sh
02 #
003 10porpag3.sh 03 # Lista enumerando os programas com extensão .sh no
004 alo1.sh 04 # diretório corrente; executa o escolhido pelo operador
005 alo2.sh 05 #
006 contpal.sh 06 clear; i=1
007 fazmenu.sh 07 printf "%11st%snn" Opção Programa
008 logaute.sh 08 CASE='case $opt in'
009 monbg.sh 09 for arq in *.sh
010 readpipe.sh 10 do
011 redirread.sh 11 printf "t%03dt%sn" $i $arq
Informe a opção desejada: 12 CASE="$CASE
13 "$(printf "%03d)t %s;;" $i $arq)
Seria interessante incluir uma opção 14 i=$((i+1))
para terminar o programa e, para isso, 15 done
seria necessária a inclusão de uma linha 16 printf "t%dt%snn" 999 "Fim do programa" # Linha incluída
após o loop de montagem da tela e a alte- 17 CASE="$CASE
ração da linha na qual fazemos a atribui- 18 999) exit;; # Linha alterada
ção final do valor da variável $CASE. Veja 19 *) ./erro;;
20 esac"
na listagem 3 como ele ficaria:
21 read -n3 -p "Informe a opção desejada: " opt
Existe no Linux uma coisa chamada
22 echo
sinal (signal). Existem diversos sinais
23 eval "$CASE"
que podem ser mandados para (ou gera-
88 julho 2005 edição 10
www.linuxmagazine.com.br
4. Papo de Botequim Linux User
O comando trap Caso a transferência seja interrompida Tabela 1: Principais sinais
Para fazer a monitoração de sinais existe por um kill ou um [CTRL]+[C], certa-
Código Nome Gerado por:
o comando trap, cuja sintaxe pode ser mente deixará lixo no disco. É exatamen-
0 EXIT Fim normal do programa
uma das mostradas a seguir: te essa a forma mais comum de uso do 1 SIGHUP Quando o programa
comando trap. Como isso é trecho de recebe um kill -HUP
trap "cmd1; cmd2; cmdn" S1 S2 … SN um script devemos, logo no início dele, 2 SIGINT Interrupção pelo teclado.
trap 'cmd1; cmd2; cmdn' S1 S2 … SN digitar o comando: ([CTRL]+[C])
3 SIGQUIT Interrupção pelo teclado
([CTRL]+[])
Onde os comandos cmd1, cmd2, cmdn trap "rm -f /tmp/$$ ; exit" 0 1 2 3 15
15 SIGTERM Quando o programa
serão executados caso o programa receba recebe um kill ou
os sinais S1, S2 … SN. As aspas (") ou Dessa forma, caso houvesse uma inter- kill -TERM
as apóstrofes (') só são necessárias caso rupção brusca (sinais 1, 2 , 3 ou 15) antes
o trap possua mais de um comando cmd do programa encerrar (no exit dentro do
associado. Cada uma delas pode ser tam- comando trap), ou um fim normal (sinal 1º Caso: O comando ftp encontra-se
bém uma função interna, uma externa 0), o arquivo /tmp/$$ seria removido. em script1. Nesse caso, o argumento do
ou outro script. Caso não houvesse a instrução exit comando trap deveria vir entre aspas (")
Para entender o uso de aspas (") e na linha de comando do trap, ao final porque, caso ocorresse uma interrupção
apóstrofes (') vamos recorrer a um da execução dessa linha o fluxo do pro- ([CTRL]+[C] ou [CTRL]+[]) no script2,
exemplo que trata um fragmento de grama retornaria ao ponto em que estava a linha só seria interpretada nesse mo-
um script que faz uma transferência de quando recebeu o sinal que originou a mento e o PID do script2 seria diferente
arquivos via FTP para uma máquina execução desse trap. do encontrado em /tmp/$$ (não esqueça
remota ($RemoComp), na qual o usuário Note também que o Shell pesquisa a que $$ é a variável que contém o PID do
é $Fulano, sua senha é $Segredo e o linha de comando uma vez quando o trap processo ativo);
arquivo a ser enviado é $Arq. Suponha é interpretado (e é por isso que é usual 2º Caso: O comando ftp encontra-se
ainda que essas quatro variáveis foram colocá-lo no início do programa) e nova- em script2. Nesse caso, o argumento
recebidas por uma rotina anterior de mente quando um dos sinais listados é do comando trap deveria estar entre
leitura e que esse script seja muito usado recebido. Então, no último exemplo, o va-apóstrofes ('), pois caso a interrupção
por diversas pessoas. Vejamos o trecho lor de $$ será substituído no momento em se desse durante a execução de script1,
de código a seguir: que o comando trap é lido pela primeira o arquivo não teria sido criado; caso ela
vez, já que as aspas (") não protegem o ocorresse durante a execução de script2,
ftp -ivn $RemoComp << FimFTP >> /tmp/$$ U cifrão ($) da interpretação do Shell. o valor de $$ seria o PID desse processo,
2>> /tmp/$$ Se você quisesse fazer a substituição que coincidiria com o de /tmp/$$.
user $Fulano $Segredo somente ao receber o sinal, o comando O comando trap, quando executado
binary deveria ser colocado entre apóstrofes (').
sem argumentos, lista os sinais que estão
get $Arq Assim, na primeira interpretação do trap,sendo monitorados no ambiente, bem
FimFTP o Shell não veria o cifrão ($), as apóstro-
como a linha de comando que será exe-
fes (') seriam removidas e, finalmente, o cutada quando tais sinais forem recebidos.
Repare que tanto as saídas dos diálo- Se a linha de comandos do trap for nula
Shell poderia substituir o valor da variá-
gos do FTP como os erros encontrados vel. Nesse caso, a linha ficaria assim: (vazia), isso significa que os sinais espe-
estão sendo redirecionados para /tmp/$$, cificados devem ser ignorados quando
o que é uma construção bastante comum trap 'rm -f /tmp/$$ ; exit' 0 1 2 3 15 recebidos. Por exemplo, o comando trap
para arquivos temporários usados em "" 2 especifica que o sinal de interrup-
scripts com mais de um usuário, porque Suponha dois casos: você tem dois ção ([CTRL]+[C]) deve ser ignorado. No
$$ é a variável que contém o número do scripts que chamaremos de script1, cuja último exemplo, note que o primeiro ar-
processo (PID), que é único. Com esse primeira linha será um trap, e script2, gumento deve ser especificado para que o
tipo de construção evita-se que dois ou colocado em execução por script1. Por sinal seja ignorado e não é equivalente a
mais usuários disputem a posse e os di- serem dois processos diferentes, terão escrever trap 2, cuja finalidade é retornar
reitos sobre um arquivo. dois PIDs distintos. o sinal 2 ao seu estado padrão. ➟
julho 2005 edição 10 89
www.linuxmagazine.com.br
5. Linux User Papo de Botequim
Se você ignorar um sinal, todos os sub- Para terminar esse assunto, abra um cadeiadeopcoes deve ser abc. Se você
shells irão ignorá-lo. Portanto, se você console gráfico e escreva no prompt de desejar que uma opção seja seguida por
especificar qual ação deve ser tomada comando o seguinte: um argumento, ponha um sinal de dois
quando receber um sinal, todos os sub- pontos (:) depois da letra, como em a:bc.
shells irão tomar a mesma ação quando $ trap "echo Mudou o tamanho da janela" 28 Isso diz ao getopts que a opção -a tem a
receberem esse sinal. Ou seja, os sinais forma -a argumento. Normalmente um
são automaticamente exportados. Para o Em seguida, pegue o mouse e arraste-o ou mais espaços em branco separam o
sinal mostrado (sinal 2), isso significa que de forma a variar o tamanho da janela parâmetro da opção; no entanto, getopts
os sub-shells serão encerrados. Suponha corrente. Surpreso? É o Shell orientado também manipula parâmetros que vêm
que você execute o comando trap "" 2 e a eventos… Mais unzinho, porque não colados à opção como em -aargumento.
então execute um sub-shell, que tornará a consigo resistir. Escreva isto: cadeiadeopcoes não pode conter um si-
executar outro script como um sub-shell. nal de interrogação (?).
Se for gerado um sinal de interrupção, $ trap "echo já era" 17 O nome constante da linha de sintaxe
este não terá efeito nem sobre o Shell acima define uma variável que receberá,
principal nem sobre os sub-shell por ele Em seguida digite: a cada vez que o comando getopts for
chamados, já que todos eles ignorarão executado, o próximo dos parâmetros
o sinal. $ sleep 3 & posicionais e o colocará na variável nome.
Em korn shell (ksh) não existe a opção getopts coloca uma interrogação (?) na
-s do comando read para ler uma senha. Você acabou de criar um sub-shell que variável definida em nome se achar uma
O que costumamos fazer é usar usar o irá dormir durante três segundos em opção não definida em cadeiadeopcoes
comando stty com a opção -echo, que background. Ao fim desse tempo, você ou se não achar o argumento esperado
inibe a escrita na tela até que se encon- receberá a mensagem “já era”, porque o para uma determinada opção.
tre um stty echo para restaurar essa sinal 17 é emitido a cada vez em que um Como já sabemos, cada opção passada
escrita. Então, se estivéssemos usando o sub-shell termina a sua execução. Para por uma linha de comandos tem um ín-
interpretador ksh, a leitura da senha teria devolver esses sinais ao seu comporta- dice numérico; assim, a primeira opção
que ser feita da seguinte forma: mento padrão, digite: trap 17 28. estará contida em $1, a segunda em $2 e
Muito legal esse comando, né? Se você assim por diante. Quando o getopts obtém
echo -n "Senha: " descobrir algum material bacana sobre uma opção, ele armazena o índice do
stty -echo uso de sinais, por favor me informe por próximo parâmetro a ser processado na
read Senha email, porque é muito rara a literatura variável OPTIND.
stty echo sobre o assunto. Quando uma opção tem um argumento
associado (indicado pelo : na cadeiade-
O problema com esse tipo de constru- Comando getopts opcoes), getopts armazena o argumento
ção é que, caso o operador não soubes- O comando getopts recupera as opções e na variável OPTARG. Se uma opção não
se a senha, ele provavelmente teclaria seus argumentos de uma lista de parâ- possuir argumento ou se o argumento
[CTRL]+[C] ou um [CTRL]+[] durante metros de acordo com a sintaxe POSIX.2, esperado não for encontrado, a variável
a instrução read para descontinuar o pro- isto é, letras (ou números) após um sinal OPTARG será "apagada" (com unset). O co-
grama e, caso agisse dessa forma, o seu de menos (-) seguidas ou não de um mando encerra sua execução quando:
terminal estaria sem echo. Para evitar que argumento; no caso de somente letras P Encontra um parâmetro que não come-
isso aconteça, o melhor a fazer é: (ou números), elas podem ser agrupa- ça com um hífen (-).
das. Você deve usar esse comando para P O parâmetro especial -- indica o fim
echo -n "Senha: " "fatiar" opções e argumentos passados das opções.
trap "stty echo para o seu script. P Quando encontra um erro (por exemplo,
exit" 2 3 A sintaxe é getopts cadeiadeopcoes uma opção não reconhecida).
stty -echo nome. A cadeiadeopcoes deve explicitar O exemplo da listagem 4 é meramente
read Senha uma cadeia de caracteres com todas as didático, servindo para mostrar, em um
stty echo opções reconhecidas pelo script; assim, pequeno fragmento de código, o uso ple-
trap 2 3 se ele reconhece as opções -a -b e –c, no do comando.
90 julho 2005 edição 10
www.linuxmagazine.com.br
6. Papo de Botequim Linux User
Para entender melhor, vamos executar o script: OPTARG eh 'impressora'
Dispensando os primeiros $OPTIND-1 = 3 argumentos
$ getoptst.sh -h -Pimpressora arq1 arq2 O que sobrou da linha de comandos foi 'arq1 arq2'
getopts fez a variavel OPT_LETRA igual a 'h'
OPTARG eh '' Repare, no exemplo a seguir, que se passarmos uma opção inválida a
getopts fez a variavel OPT_LETRA igual a 'P' variável $OPT_LETRA receberá um ponto de interrogação (?) e a $OPTARG
OPTARG eh 'impressora' será "apagada" (unset).
Dispensando os primeiros $OPTIND-1 = 2 argumentos
O que sobrou da linha de comandos foi 'arq1 arq2' $ getoptst.sh -f -Pimpressora arq1 arq2 # A opção –f não é valida
./getoptst.sh: illegal option -- f
Dessa forma, sem ter muito trabalho, separei getopts fez a variavel OPT_LETRA igual a '?'
todas as opções com seus respectivos argumentos, OPTARG eh ''
deixando somente os parâmetros que foram passa- getopts fez a variavel OPT_LETRA igual a 'P'
dos pelo operador para posterior tratamento. Repare OPTARG eh 'impressora'
que, se tivéssemos escrito a linha de comando com Dispensando os primeiros $OPTIND-1 = 2 argumentos
o argumento (impressora) separado da opção (-P), O que sobrou da linha de comandos foi 'arq1 arq2'
o resultado seria exatamente o mesmo, exceto pelo
OPTIND, já que nesse caso ele identifica um conjun- – Me diz uma coisa: você não poderia ter usado um condicional com
to de três opções (ou argumentos) e, no anterior, case para evitar o getopts?
somente dois. Veja só: – Poderia sim, mas para quê? Os comandos estão aí para serem usados…
O exemplo foi didático, mas imagine um programa que aceitasse muitas
$ getoptst.sh -h -P impressora arq1 arq2 opções e cujos parâmetros poderiam ou não estar colados às opções, sen-
getopts fez a variavel OPT_LETRA igual a 'h' do que as opções também poderiam ou não estar coladas: ia ser um case
OPTARG eh '' infernal! Com getopts, é só seguir os passos acima.
getopts fez a variavel OPT_LETRA igual a 'P' – É… Vendo dessa forma, acho que você tem razão. É porque eu já estou
meio cansado com tanta informação nova na minha
Listagem 4: getoptst.sh cabeça. Vamos tomar a saideira ou você ainda quer
01 $ cat getoptst.sh explicar alguma particularidade do Shell?
02 #!/bin/sh – Nem um nem outro, eu também já cansei mas
03 hoje não vou tomar a saideira porque estou indo
04 # Execute assim: dar aula na UniRIO, que é a primeira universidade
05 # federal que está preparando seus alunos do curso
06 # getoptst.sh -h -Pimpressora arq1 arq2 de graduação em Informática para o uso de Soft-
07 #
ware Livre. Mas antes vou te deixar um problema
08 # e note que as informações de todas as opções são exibidas
para te encucar: quando você varia o tamanho de
09 #
10 # A cadeia 'P:h' diz que a opção -P é uma opção complexa uma janela do terminal, no centro dela não aparece
11 # e requer um argumento e que h é uma opção simples que não requer dinamicamente, em vídeo reverso, a quantidade de
12 # argumentos. linhas e colunas? Então! Eu quero que você repro-
13 duza isso usando a linguagem Shell. Chico, traz
14 while getopts 'P:h' OPT_LETRA rapidinho a minha conta! Vou contar até um e se
15 do você não trouxer eu me mando!
16 echo "getopts fez a variavel OPT_LETRA igual a '$OPT_LETRA'"
Não se esqueça, qualquer dúvida ou falta de compa-
17 echo " OPTARG eh '$OPTARG'"
nhia para um chope é só mandar um email para julio.
18 done
19 used_up=`expr $OPTIND – 1`
neves@gmail.com. Vou aproveitar também para mandar
20 echo "Dispensando os primeiros $OPTIND-1 = $used_up argumentos" o meu jabá: diga para os amigos que quem estiver a
21 shift $used_up fim de fazer um curso porreta de programação em
22 echo "O que sobrou da linha de comandos foi '$*'" Shell que mande um e-mail para julio.neves@tecnohall.
com.br para informar-se. Valeu! ■
julho 2005 edição 10 91
www.linuxmagazine.com.br