You are here:
Wiki-SL
>
TWikiBar Web
>
TWikiBarPapo010
(01 Aug 2009,
BrSalgado
)
(raw view)
E
dit
A
ttach
---+!! Papo de botequim parte X --- %TOC% --- - E aê amigo, te dei a maior moleza, né? Um exerciciozinho muito simples... - É mais nos testes que eu fiz, e de acordo com o que você ensinou sobre substituição de parâmetros, achei que deveria fazer outras alterações nas funções que desenvolvemos para torná-las de uso geral como você me disse que todas as funções deveriam ser, quer ver? - Claro né mané, se te pedi para fazer é porque estou afim de te ver aprender, mas peraí, dá um tempo! - Chico! Manda dois, um sem colarinho! - Vai, mostra aí o que você fez. - Bem, além do que você pediu, eu reparei que o programa que chamava a função, teria de ter previamente definidas a linha em que seria dada a mensagem e a quantidade de colunas. O que fiz foi incluir duas linhas - nas quais empreguei substituição de parâmetros - que caso uma destas variáveis não fosse informada, a própria função atribuiria. A linha de mensagem seria três linhas acima do fim da tela e o total de colunas seria obtido pelo comando tput cols. Veja como ficou: %TERMINAL_INI% $ cat pergunta.func%OUT_INI% # A funcao recebe 3 parametros na seguinte ordem: # $1 - Mensagem a ser dada na tela # $2 - Valor a ser aceito com resposta default # $3 - O outro valor aceito # Supondo que $1=Aceita?, $2=s e $3=n, a linha # abaixo colocaria em Msg o valor "Aceita? (S/n)" <nop>TotCols=${TotCols:-$(tput cols)} # Se nao estava definido, agora esta <nop>LinhaMesg=${LinhaMesg:-$(($(tput lines)-3))} # Idem Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" <nop>TamMsg=${#Msg} Col=$(((<nop>TotCols - <nop>TamMsg) / 2)) # Para centrar Msg na linha tput cup $LinhaMesg $Col read -n1 -p "$Msg " SN SN=${SN:-$2} # Se vazia coloca default em SN SN=$(echo $SN | tr A-Z a-z) # A saida de SN serah em minuscula tput cup $LinhaMesg $Col; tput el # Apaga msg da tela%OUT_FIM% %TERMINAL_FIM% - Gostei, você já se antecipou ao que eu ia pedir. Só pra gente encerrar este papo de substituição de parâmetros, repare que a legibilidade está horrorível, mas a performance, isto é, velocidade de execução, está ótima. Como funções são coisas muito pessoais, já que cada um usa as suas, e quase não dão manutenção, eu sempre opto pela performance. - Hoje vamos sair daquela chatura que foi o nosso último papo e vamos voltar à lógica saindo da decoreba, mas volto a te lembrar, tudo que eu te mostrei da outra vez aqui no Boteco do Chico é válido e quebra um galhão, guarde aqueles guardanapos que rabiscamos que, mais cedo ou mais tarde, vão te ser muito úteis. ---++ O comando eval - Vou te dar um problema que eu duvido que você resolva: %TERMINAL_INI% $ var1=3 $ var2=var1 %TERMINAL_FIM% - Te dei estas duas variáveis, e quero que você me diga como eu posso, só me referindo a =$var2=, listar o valor de =$var1= (=3=). - A isso é mole, é só fazer: <verbatim> echo $`echo $var2` </verbatim> - Repare que eu coloquei o echo =$var2= entre crases (=`=), que desta forma terá prioridade de execução e resultará em =var1=, montando =echo$var1= que produzirá =3=... - A é? Então execute para ver se está correto. %TERMINAL_INI% $ echo $`echo $var2`%OUT_INI% $var1%OUT_FIM% %TERMINAL_FIM% - Ué! Que foi que houve? O meu raciocínio me parecia bastante lógico... - O seu raciocínio realmente foi lógico, o problema é que você esqueceu de uma das primeiras coisas que te falei aqui no Boteco e vou repetir. O _Shell_ usa a seguinte ordem para resolver uma linha de comandos: * Resolve os redirecionamentos; * Substitui as variáveis pelos seus valores; * Resolve e substitui os meta caracteres; * Passa a linha já toda esmiuçada para execução. Desta forma, quando chegou na fase de resolução de variáveis, que como eu disse é anterior à execução, a única variável existente era =$var2= e por isso a tua solução produziu como saída =$var1=. O comando =echo= identificou isso como uma cadeia e não como uma variável. Problemas deste tipo são relativamente freqüentes e seriam insolúveis caso não existisse a instrução =eval=, cuja sintaxe é: <verbatim> eval cmd </verbatim> Onde =cmd= é uma linha de comando qualquer que você poderia inclusive executar direto no _prompt_ do terminal. Quando você põe o =eval= na frente, no entanto, o que ocorre é que o _Shell_ trata =cmd= como se seus dados fossem parâmetros do =eval= e em seguida o =eval= executa a linha recebida, submetendo-a ao _Shell_, dando então na prática duas passadas em =cmd=. Desta forma se executássemos o comando que você propôs colocando o =eval= à sua frente, teríamos a saída esperada, veja: %TERMINAL_INI% $ eval echo $`echo $var2`%OUT_INI% 3%OUT_FIM% %TERMINAL_FIM% Este exemplo também poderia ter sido feito da seguinte maneira: %TERMINAL_INI% $ eval echo \$$var2%OUT_INI% 3%OUT_FIM% %TERMINAL_FIM% Na primeira passada a contrabarra (=\=) seria retirada e =$var2= seria resolvido produzindo =var1=, para a segunda passada teria sobrado echo =$var1=, que produziria o resultado esperado. Agora vou colocar um comando dentro de =var2=: %TERMINAL_INI% $ var2=ls %TERMINAL_FIM% Vou executar: %TERMINAL_INI% $ $var2%OUT_INI% 10porpag1.sh alo2.sh listamusica logaute.sh 10porpag2.sh confuso listartista mandamsg.func 10porpag3.sh contpal.sh listartista3 monbg.sh alo1.sh incusu logado%OUT_FIM% %TERMINAL_FIM% Agora vamos colocar em =var2= o seguinte: =ls $var1=; e em =var1= vamos colocar =l*=, vejamos: %TERMINAL_INI% $ var2='ls $var1' $ var1='l*' $ $var2%OUT_INI% ls: $var1: No such file or directory%OUT_FIM% $ eval $var2%OUT_INI% listamusica listartista listartista3 logado logaute.sh%OUT_FIM% %TERMINAL_FIM% Novamente, no tempo de substituição das variáveis, =$var1= ainda não havia se apresentado ao _Shell_ para ser resolvida, desta forma só nos resta executar o comando =eval= para dar as duas passadas necessárias. Uma vez um colega de uma <a href="http://br.groups.yahoo.com/group/shell-script" target="_blank"><b>excelente lista sobre <i>Shell Script</i></b></a>, colocou uma dúvida: queria fazer um menu que numerasse e listasse todos os arquivos com extensão =.sh= e quando o operador escolhesse uma opção, o programa correspondente seria executado. A minha proposta foi a seguinte: %TERMINAL_INI% $ cat fazmenu%OUT_INI% #!/bin/bash # # Lista numerando os programas com extensão .sh no # diretório corrente e executa o escolhido pelo operador # clear; i=1 printf "%11s\t%s\n\n" Opção Programa CASE='case $opt in' for arq in *.sh do printf "\t%03d\t%s\n" $i $arq CASE="$CASE "$(printf "%03d)\t %s;;" $i $arq) i=$((i+1)) done CASE="$CASE *) . erro;; esac" read -n3 -p "Informe a opção desejada: " opt echo eval "$CASE"%OUT_FIM% %TERMINAL_FIM% Parece complicado porque usei muito =printf= para formatação da tela, mas é bastante simples, vamos entendê-lo: o primeiro =printf= foi colocado para fazer o cabeçalho e logo em seguida comecei a montar dinamicamente a variável =$CASE=, na qual ao final será feito um =eval= para execução do programa escolhido. Repare no entanto que dentro do _loop_ do =for= existem dois =printf=: o primeiro serve para formatar a tela e o segundo para montar o =case= (se antes do comando =read= você colocar uma linha =echo "$CASE"=, verá que o comando =case= montado dentro da variável está todo indentado. Frescura, né? :). Na saída do =for=, foi adicionada uma linha à variável =$CASE=, para no caso de se fazer uma opção inválida, ser executada uma função externa para dar mensagens de erro. Vamos executá-lo para ver a saída gerada: %TERMINAL_INI% $ fazmenu.sh%OUT_INI% Opcao Programa 001 10porpag1.sh 002 10porpag2.sh 003 10porpag3.sh 004 alo1.sh 005 alo2.sh 006 contpal.sh 007 fazmenu.sh 008 logaute.sh 009 monbg.sh 010 readpipe.sh 011 redirread.sh Informe a opção desejada:%OUT_FIM% %TERMINAL_FIM% Neste programa seria interessante darmos uma opção de término, e para isso seria necessário a inclusão de uma linha após o _loop_ de montagem da tela e alterarmos a linha na qual fazemos a atribuição final do valor da variável =$CASE=. Vejamos como ele ficaria: %TERMINAL_INI% $ cat fazmenu%OUT_INI% #!/bin/bash # # Lista numerando os programas com extensão .sh no # diretório corrente e executa o escolhido pelo operador # clear; i=1 printf "%11s\t%s\n\n" Opção Programa CASE='case $opt in' for arq in *.sh do printf "\t%03d\t%s\n" $i $arq CASE="$CASE "$(printf "%03d)\t %s;;" $i $arq) i=$((i+1)) done printf "\t%d\t%s\n\n" 999 "Fim do programa" # Linha incluida CASE="$CASE 999) exit;; # Linha alterada *) ./erro;; esac" read -n3 -p "Informe a opção desejada: " opt echo eval "$CASE"%OUT_FIM% %TERMINAL_FIM% ---++ Sinais de Processos Existe no Linux uma coisa chamada sinal (_signal_). Existem diversos sinais que podem ser mandados para (ou gerados por) processos em execução. Vamos de agora em diante dar uma olhadinha nos sinais mandados para os processos e mais à frente vamos dar uma passada rápida pelos sinais gerados por processos. ---+++ Sinais assassinos Para mandar um sinal a um processo, usamos normalmente o comando =kill=, cuja sintaxe é: <verbatim> kill -sig PID </verbatim> Onde =PID= é o identificador do processo (_<kbd>P</kbd>rocess <kbd>ID</kbd>entification_ ou _<kbd>P</kbd>rocess <kbd>ID</kbd>_). Além do comando =kill=, algumas seqüências de teclas também podem gerar =sig=. A tabela a seguir mostra os sinais mais importantes para monitorarmos: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Sinais Mais Importantes* ||| | <b>Sinal</b> || <b> Gerado por:</b> | | 0 | EXIT | Fim normal do programa | | 1 | SIGHUP | Quando recebe um kill -HUP | | 2 | SIGINT | Interrupção pelo teclado (<CTRL+C>) | | 3 | SIGQUIT | Interrupção pelo teclado (<CTRL+\>) | | 15 | SIGTERM | Quando recebe um kill ou kill -TERM | </center> Além destes sinais, existe o famigerado =-9= ou =SIGKILL= que, para o processo que o está recebendo, equivale a meter o dedo no botão de desliga do computador o que seria altamente indesejável já que muitos programas necessitam "limpar o meio de campo" ao seu término. Se o seu final ocorrer de forma prevista, ou seja se tiver um término normal, é muito fácil de fazer esta limpeza, porém se o seu programa tiver um fim brusco muita coisa pode ocorrer: * É possível que em um determinado espaço de tempo, o seu computador esteja cheio de arquivos de trabalho inúteis * Seu processador poderá ficar atolado de processos _zombies_ e _defuncts_ gerados por processos filhos que perderam os pais; * É necessário liberar _sockets_ abertos para não deixar os clientes congelados; * Seus bancos de dados poderão ficar corrompidos porque sistemas gerenciadores de bancos de dados necessitam de um tempo para gravar seus _buffers_ em disco (_commit_). Enfim, existem mil razões para não usar um =kill= com o sinal =-9= e para monitorar fins anormais de programas. ---+++ O trap não atrapalha Para fazer a monitoração descrita acima existe o comando =trap= cuja sintaxe é: <verbatim> trap "cmd1; cmd2; cmdn" S1 S2 ... SN </verbatim> ou <verbatim> trap 'cmd1; cmd2; cmdn' S1 S2 ... SN </verbatim> Onde os comandos =cmd1=, =cmd2=, =cmdn= serão executados caso o programa receba os sinais =S1 S2= ... =SN=. As aspas (") ou os apóstrofos (') só são necessários caso o =trap= possua mais de um comando =cmd= associado. Cada um dos =cmd= pode ser também uma função interna, uma externa ou outro _script_. Para entender o uso de aspas (") e apóstrofos (') vamos recorrer a um exemplo que trata um fragmento de um _script_ que faz um =ftp= para uma máquina remota (=$RemoComp=), na qual o usuário é =$Fulano=, sua senha é =$Segredo= e vai transmitir o arquivo contido em =$Arq=. Suponha ainda que estas quatro variáveis foram recebidas em uma rotina anterior de leitura e que este _script_ é muito usado por diversas pessoas da instalação. Vejamos este trecho de código: <verbatim> ftp -ivn $RemoComp << FimFTP >> /tmp/$$ 2>> /tmp/$$ user $Fulano $Segredo binary get $Arq FimFTP </verbatim> Repare que, tanto as saídas do dos diálogos do =ftp=, como os erros encontrados, estão sendo redirecionados para =/tmp/$$=, o que é uma construção bastante normal para arquivos temporários usados em _scripts_ com mais de um usuário, porque =$$= é a variável que contém o número do processo (=PID=), que é único, e com este tipo de construção evita-se que dois ou mais usuários disputem a posse e os direitos sobre o arquivo. Caso este =ftp= seja interrompido por um =kill= ou um =<CTRL+C>=, certamente deixará lixo no disco. É exatamente esta a forma como mais se usa o comando =trap=. Como isto é trecho de um _script_, devemos, logo no seu início, como um de seus primeiros comandos, fazer: <verbatim> trap "rm -f /tmp/$$ ; exit" 0 1 2 3 15 </verbatim> Desta forma, caso houvesse uma interrupção brusca (sinais =1=, =2=, =3= ou =15=) antes do programa encerrar (no =exit= dentro do comando =trap=), ou um fim normal (sinal =0=), o arquivo =/tmp/$$= seria removido. Caso na linha de comandos do =trap= não houvesse a instrução =exit=, ao final da execução desta linha o fluxo do programa retornaria ao ponto em que estava quando recebeu o sinal que originou a execução deste =trap=. Este =trap= poderia ser subdividido, ficando da seguinte forma: <verbatim> trap "rm -f /tmp/$$" 0 trap "exit" 1 2 3 15 </verbatim> Assim ao receber um dos sinais o programa terminaria, e ao terminar, geraria um sinal =0=, que removeria o arquivo. Caso seu fim seja normal, o sinal também será gerado e o =rm= será executado. Note também que o _Shell_ pesquisa a linha de comandos uma vez quanto o =trap= é interpretado (e é por isso que é usual colocá-lo no início do programa) e novamente quando um dos sinais listados é recebido. Então, no último exemplo, o valor de =$$= será substituído no momento que o comando =trap= foi lido da primeira vez, já que as aspas (="=) não protegem o cifrão (=$=) da interpretação do _Shell_. Se você desejasse que a substituição fosse realizada somente quando recebesse o sinal, o comando deveria ser colocado entre apóstrofos (='=). Assim, na primeira interpretação do =trap=, o _Shell_ não veria o cifrão (=$=), porém os apóstrofos (='=) seriam removidos e finalmente o _Shell_ poderia substituir o valor da variável. Neste caso, a linha ficaria da seguinte maneira: <verbatim> trap 'rm -f /tmp/$$ ; exit' 0 1 2 3 15 </verbatim> Suponha dois casos: você tem dois _scripts_ que chamaremos de =script1=, cuja primeira linha será um =trap= e =script2=, sendo este último colocado em execução pelo primeiro, e por serem dois processos, terão dois =PID= distintos. * 1º Caso: O =ftp= encontra-se em =script1= %BR%Neste caso, o argumento do comando =trap= deveria vir entre aspas (="=) porque caso ocorresse uma interrupção (=<CTRL+C>= ou =<CTRL+\>=) no =script2=, a linha só seria interpretada neste momento e o =PID= do =script2= seria diferente do encontrado em =/tmp/$$= (não esqueça que =$$= é a variável que contém o =PID= do processo ativo); * 2º Caso: O =ftp= acima encontra-se em =script2= %BR%Neste caso, o argumento do comando =trap= deveria estar entre apóstrofos (='=), pois caso a interrupção se desse durante a execução de =script1=, o arquivo não teria sido criado, caso ocorresse durante a execução de =script2=, o valor de =$$= seria o =PID= deste processo, que coincidiria com o de =/tmp/$$=. O comando =trap=, quando executado sem argumentos, lista os sinais que estão sendo monitorados no ambiente, bem como a linha de comando que será executada quando tais sinais forem recebidos. Se a linha de comandos do =trap= for nula (vazia), isto significa que os sinais especificados devem ser ignorados quando recebidos. Por exemplo, o comando: <verbatim> trap "" 2 </verbatim> Especifica que o sinal de interrupção (=<CTRL+C>=) deve ser ignorado. No caso citado, quando não se deseja que sua execução seja interrompida. No último exemplo note que o primeiro argumento deve ser especificado para que o sinal seja ignorado, e não é equivalente a escrever o seguinte, cuja finalidade é retornar o sinal =2= ao seu estado padrão (_default_): <verbatim> trap 2 </verbatim> Se você ignora um sinal, todos os _Subshells_ irão ignorar este sinal. Portanto, se você especifica qual ação deve ser tomada quando receber um sinal, então todos os _Subshells_ irão também tomar a ação quando receberem este sinal, ou seja, os sinais são automaticamente exportados. Para o sinal que temos mostrado (sinal =2=), isto significa que os Subshells serão encerrados. Suponha que você execute o comando: <verbatim> trap "" 2 </verbatim> e então execute um _Subshell_, que tornará a executar outro _script_ como um _Subshell_. Se for gerado um sinal de interrupção, este não terá efeito nem sobre o _Shell_ principal nem sobre os _Subshell_ por ele chamados, já que todos eles ignorarão o sinal. Outra forma de restaurar um sinal ao seu default é fazendo: <verbatim> trap - sinal </verbatim> Em _korn shell_ (=ksh=) não existe a opção =-s= do comando =read= para ler uma senha. O que costumamos fazer é usar o comando =stty= com a opção =-echo= que inibe a escrita na tela até que se encontre um =stty echo= para restaurar esta escrita. Então, se estivéssemos usando o interpretador =ksh=, a leitura da senha teria que ser feita da seguinte forma: <verbatim> echo -n "Senha: " stty -echo read Senha stty echo </verbatim> O problema neste tipo de construção é que caso o operador não soubesse a senha, ele provavelmente daria um =<CTRL+C>= ou um =<CTRL+\>= durante a instrução =read= para descontinuar o programa e, caso ele agisse desta forma, o que quer que ele escrevesse, não apareceria na tela do seu terminal. Para evitar que isso aconteça, o melhor a fazer é: <verbatim> echo -n "Senha: " trap "stty echo exit" 2 3 stty -echo read Senha stty echo trap 2 3 </verbatim> Para terminar este assunto, abra uma console gráfica e escreva no prompt de comando o seguinte: %TERMINAL_INI% $ trap "echo Mudou o tamanho da janela" 28 %TERMINAL_FIM% Em seguida, pegue o _mouse_ (arghh!!) e arraste-o de forma a variar o tamanho da janela corrente. Surpreso? É o Shell orientado a eventos... :) Mais unzinho porque não pude resistir. Agora escreva assim: %TERMINAL_INI% $ trap "echo já era" 17 %TERMINAL_FIM% Em seguida faça: %TERMINAL_INI% $ sleep 3 & %TERMINAL_FIM% Você acabou de criar um _subshell_ que irá dormir durante três segundos em _background_. Ao fim deste tempo, você receberá a mensagem =já era=, porque o sinal =17= é emitido a cada vez que um _subshell_ termina a sua execução. Para devolver estes sinais aos seus defaults, faça: %TERMINAL_INI% $ trap 17 28 %TERMINAL_FIM% Ou %TERMINAL_INI% $ trap - 17 28 %TERMINAL_FIM% Acabamos de ver mais dois sinais que não são tão importante como os que vimos anteriormente, mas vou registrá-los na tabela a seguir: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Sinais Não Muito Importantes* ||| | <b>Sinal</b> || <b> Gerado por:</b> | | 17 | SIGCHLD | Fim de um processo filho | | 28 | SIGWINCH | Mudança no tamanho da janela gráfica | </center> Muito legal este comando, né? Se você descobrir algum caso bacana de uso de sinais, por favor me informe por e-mail porque é muito rara a literatura sobre o assunto. ---++ Comando getopts O comando =getopts= recupera as opções e seus argumentos de uma lista de parâmetros de acordo com a sintaxe POSIX.2, isto é, letras (ou números) após um sinal de menos (=-=) seguidas ou não de um argumento; no caso de somente letras (ou números) elas podem ser agrupadas. Você deve usar este comando para "fatiar" opções e argumento passados para o seu _script_. Sintaxe: <verbatim> getopts cadeiadeopcoes nome </verbatim> A =cadeiadeopcoes= deve explicitar uma cadeia de caracteres com todas as opções reconhecidas pelo _script_, assim se ele reconhece as opções =-a= =-b= e =-c=, =cadeiadeopcoes= deve ser =abc=. Se você deseja que uma opção seja seguida por um argumento, ponha dois-pontos (=:=) depois da letra, como em =a:bc=. Isto diz ao =getopts= que a opção =-a= tem a forma: <verbatim> -a argumento </verbatim> Normalmente um ou mais espaços em branco separam o parâmetro da opção; no entanto, =getopts= também manipula parâmetros que vêm colados à opção como em: <verbatim> -aargumento </verbatim> =cadeiadeopcoes= não pode conter interrogação (=?=). O =nome= constante da linha de sintaxe acima, define uma variável que cada vez que o comando =getopts= for executado, receberá a próxima opção dos parâmetros posicionais e a colocará na variável =nome=. =getopts= coloca uma interrogação (=?=) na variável definida em =nome= se achar uma opção não definida em =cadeiadeopcoes= ou se não achar o argumento esperado para uma determinada opção. Como já sabemos, cada opção passada por uma linha de comandos tem um índice numérico, assim, a primeira opção estará contida em =$1=, a segunda em =$2=, e assim por diante. Quando o =getopts= obtém uma opção, ele armazena o índice do próximo parâmetro a ser processado na variável =OPTIND=. Quando uma opção tem um argumento associado (indicado pelo =:= na =cadeiadeopcoes=), =getopts= armazena o argumento na variável =OPTARG=. Se uma opção não possui argumento ou o argumento esperado não foi encontrado, a variável =OPTARG= será "matada" (=unset=). O comando encerra sua execução quando: * Encontra um parâmetro que não começa por menos (=-=); * O parâmetro especial =--= marca o fim das opções; * Quando encontra um erro (por exemplo, uma opção não reconhecida). O exemplo abaixo é meramente didático, servindo para mostrar, em um pequeno fragmento de código o uso pleno do comando. %TERMINAL_INI% $ cat getoptst.sh%OUT_INI% #!/bin/sh # Execute assim: # # getoptst.sh -h -Pimpressora arq1 arq2 # # e note que as informacoes de todas as opcoes sao exibidas # # A cadeia 'P:h' diz que a opcao -P eh uma opcao complexa # e requer um argumento, e que h eh uma opcao simples que nao requer # argumentos. while getopts 'P:h' OPT_LETRA do echo "getopts fez a variavel OPT_LETRA igual a '$OPT_LETRA'" echo " OPTARG eh '$OPTARG'" done used_up=`expr $OPTIND - 1` echo "Dispensando os primeiros \$OPTIND-1 = $used_up argumentos" shift $used_up echo "O que sobrou da linha de comandos foi '$*'"%OUT_FIM% %TERMINAL_FIM% Para entendê-lo melhor, vamos executá-lo como está sugerido em seu cabeçalho: %TERMINAL_INI% $ getoptst.sh -h -Pimpressora arq1 arq2%OUT_INI% getopts fez a variavel OPT_LETRA igual a 'h' OPTARG eh '' getopts fez a variavel OPT_LETRA igual a 'P' OPTARG eh 'impressora' Dispensando os primeiros $OPTIND-1 = 2 argumentos O que sobrou da linha de comandos foi 'arq1 arq2'%OUT_FIM% %TERMINAL_FIM% Desta forma, sem ter muito trabalho, separei todas as opções com seus respectivos argumentos, deixando somente os parâmetros que foram passados pelo operador para posterior tratamento. Repare que se tivéssemos escrito a linha de comando com o argumento (=impressora=) separado da opção (=-P=), o resultado seria exatamente o mesmo, exceto pelo =$OPTIND=, já que neste caso ele identifica um conjunto de três opções/argumentos e no anterior somente dois. Veja só: %TERMINAL_INI% $ getoptst.sh -h -P impressora arq1 arq2%OUT_INI% getopts fez a variavel OPT_LETRA igual a 'h' OPTARG eh '' getopts fez a variavel OPT_LETRA igual a 'P' OPTARG eh 'impressora' Dispensando os primeiros $OPTIND-1 = 3 argumentos O que sobrou da linha de comandos foi 'arq1 arq2'%OUT_FIM% %TERMINAL_FIM% Repare, no exemplo a seguir, que se passarmos uma opção inválida, a variável =$OPT_LETRA= receberá um ponto-de-interrogação (=?=) e a =$OPTARG= será "apagada" (=unset=). %TERMINAL_INI% $ getoptst.sh -f -Pimpressora arq1 arq2 # A opção �f não é valida%OUT_INI% ./getoptst.sh: illegal option -- f getopts fez a variavel OPT_LETRA igual a '?' OPTARG eh '' getopts fez a variavel OPT_LETRA igual a 'P' OPTARG eh 'impressora' Dispensando os primeiros $OPTIND-1 = 2 argumentos O que sobrou da linha de comandos foi 'arq1 arq2'%OUT_FIM% %TERMINAL_FIM% - Me diz uma coisa: você não poderia ter usado um =case= para evitar o =getopts=? - Poderia sim, mas para que? Os comandos estão aí para serem usados... O exemplo dado foi didático, mas imagine um programa que aceitasse muitas opções e seus parâmetros poderiam ou não estar colados às opções, suas opções também poderiam ou não estar coladas, ia ser um =case= infernal e com =getopts= é só seguir os passos acima. - É... Vendo desta forma acho que você tem razão. É porque eu já estou meio cansado com tanta informação nova na minha cabeça. Vamos tomar a saideira ou você ainda quer explicar alguma particularidade do _Shell_? - Nem um nem outro, eu também já cansei mas hoje não vou tomar a saideira porque estou indo dar aula na <nop>UniRIO, que é a primeira universidade federal que está preparando no uso de Software Livre, seus alunos do curso de graduação em informática. Mas antes vou te deixar um problema para te encucar: quando você varia o tamanho de uma tela, no seu centro não aparece dinamicamente em vídeo reverso a quantidade de linhas e colunas? Então! Eu quero que você reproduza isso usando a linguagem _Shell_. - Chico, traz rapidinho a minha conta! Vou contar até um e se você não trouxer eu me mando! Vou aproveitar também para mandar o meu jabá: diga para os amigos que quem estiver afim de fazer um curso porreta de programação em _Shell_ que mande um e-mail para a nossa <a href="mailto:contato@clavis.com.br?Subject=Curso de Shell com Julio Neves">gerencia de treinamento</a> para informar-se. Qualquer dúvida ou falta de companhia para um chope ou até para falar mal dos políticos é só mandar um e-mail para <a href="mailto:julioneves@openoffice.org?Subject=Dúvidas Papo de Botequim">mim</a>. Valeu!
E
dit
|
A
ttach
|
P
rint version
|
H
istory
: r14
<
r13
<
r12
<
r11
<
r10
|
B
acklinks
|
V
iew topic
|
M
ore topic actions
Topic revision: r14 - 01 Aug 2009 - 22:33:57 -
BrSalgado
TWikiBar
Página Inicial
Últimas alterações
Índice
Procurar
Estatísticas de Uso
Aviso de Atualização
Configurações Gerais
Projeto Gráfico
Mapa do Site
Quem Somos
Registre-se
?
Regras de Formatação
Biblioteca Gráfica
?
Carinhas Gráficas
Webs Wiki-SL
Amadeu
Anapolivre
ArquivoLivre
Arte
BahiaSocial
BeaBa
BibliotecaLivre
Blogs
BrasilDigital
BrasilELivre
BSM
Ccsa
CESL
CoberturaWiki
Cooperativas
Curriculo
DarvinMarosin
DiaD
Dinamicoop
Economia
EconomiaSolidaria
EducacaoLivre
Ekaaty
Emacsbr
ENSL
Fatos
Festival3
Festival4
Flisol
Fmpb
Formatos
Foswikibr
FSM2005
GNOMEBR
GTTemario2004
GTWeb
Guialivre
HDC
Incubus
InkscapeBrasil
Jogos
KdeBR
KSP
LGM
LinuxStokDoc
Livros
Main
Mentores
MHHOB
MinuanoDigital
MoradiaECidadania
OlhosDagua
Olimpo
OLPC
OOPTQ
Papers
PCLivre
PentahoBrasil
Pessoas
Portal
Prefeituras
PSLAL
PSLBA
PSLBancarios
PSLBrasil
PSLGO
PSLMA
PSLMG
PSLMIP
PSLMT
PSLMulheres
PSLPI
PubFisl10
PubFisl7
PubFisl8
PubFisl9
QuilomboDoSopapo
RadioSL
RedeMesh
RedePopular
RobotWars
Sandbox
Saudelivre
Scribus
Sementes
Shakya
SLRJ
SoftwareLivreIrece
SoftwareLivreVS
SoLiSC
SuporteLivre
System
Telecentros
TeseSA
TextoLivre
TV
TWikiBar
TWikiPtbr
UNELivre
UNIMIX
VilaTorres
WebNordeste
WTRD2004
Este Menu
?skin=free
English
Español
Português brasileiro
Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-SL?
Send feedback