You are here:
Wiki-SL
>
TWikiBar Web
>
TWikiBarPapo009
(01 Aug 2009,
BrSalgado
)
(raw view)
E
dit
A
ttach
---+!! Papo de botequim parte IX --- %TOC% --- - Tá bom, já sei que você vai querer chope antes de começar, mas tô tão afim de te mostrar o que fiz que já vou até pedindo a rodada e em seguida vou te mostrar. - Aê Chico, manda dois. O dele é sem colarinho pra não deixar cheiro ruim neste bigodão... - Enquanto o chope não chega deixa eu te relembrar que você me pediu para refazer o =listartista= com a tela formatada, em _loop_, de forma que ele só termine quando receber um =<ENTER>= puro no nome do artista. Eventuais mensagens de erros e perguntas deveriam ser dadas na antepenúltima linha da tela utilizando as rotina =mandamsg.func= e =pergunta.func= que acabamos de desenvolver. - Primeiramente eu dei uma encolhida no =mandamsg.func= e no =pergunta.func=, que ficaram assim: %TERMINAL_INI% $ cat mandamsg.func%OUT_INI% # A função recebe somente um parâmetro # com a mensagem que se deseja exibir, # para não obrigar ao programador passar # a msg entre aspas, usaremos $* (todos # os parâmetro, lembra?) e não $1. Msg="$*" <nop>TamMsg=${#Msg} Col=$(((<nop>TotCols - <nop>TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col read -n1 -p "$Msg "%OUT_FIM% %TERMINAL_FIM% %TERMINAL_INI% $ cat pergunta.func%OUT_INI% # A função recebe 3 parâmetros 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)" 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)) # Centra 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 saída de SN será em minúscula tput cup $LinhaMesg $Col; tput el # Apaga msg da tela%OUT_FIM% %TERMINAL_FIM% - E agora aí vai o grandão: %TERMINAL_INI% $ cat listartista3%OUT_INI% #!/bin/bash # Dado um artista, mostra as suas musicas # versao 3 <nop>LinhaMesg=$((`tput lines` - 3)) # Linha que msgs serão dadas para operador <nop>TotCols=$(tput cols) # Qtd colunas da tela para enquadrar msgs clear echo " +----------------------------------------------------+ <nop>| Lista Todas as Músicas de um Determinado Artista | <nop>| ----- ----- -- ------- -- -- ----------- ------- | <nop>| | <nop>| Informe o Artista: | +----------------------------------------------------+" while true do tput cup 5 51; tput ech 31 # ech=Erase chars (31 caracteres para não apagar barra vertical) read Nome if [ ! "$Nome" ] # $Nome estah vazio? then . pergunta.func "Deseja Sair?" s n [ $SN = n ] && continue break fi fgrep -iq "^$Nome~" musicas || # fgrep não interpreta ^ como expressão regular { . mandamsg.func "Não existe música deste artista" continue } tput cup 7 29; echo '| |' <nop>LinAtual=8 IFS=" :" for <nop>ArtMus in $(cut -f2 -d^ musicas) # Exclui nome do album do if echo "$ArtMus" | grep -iq "^$Nome~" then tput cup $LinAtual 29 echo -n '| ' echo $ArtMus | cut -f2 -d~ tput cup $LinAtual 82 echo '|' let <nop>LinAtual++ if [ $LinAtual -eq $LinhaMesg ] then . mandamsg.func "Tecle Algo para Continuar..." tput cup 7 0; tput ed # Apaga a tela a partir da linha 7 tput cup 7 29; echo '| |' <nop>LinAtual=8 fi fi done tput cup $LinAtual 29; echo '| |' tput cup $((++LinAtual)) 29 read -n1 -p "+-----------Tecle Algo para Nova Consulta------------+" tput cup 7 0; tput ed # Apaga a tela a partir da linha 7 done%OUT_FIM% %TERMINAL_FIM% - Poxa, você chegou com a corda toda! Mas gostei da forma que você resolveu o problema e estruturou o programa. Foi mais trabalhoso mas a apresentação ficou legal e você explorou bastante as opções do =tput=. Vamos testar o resultado com um álbum do _Emerson, Lake & Palmer_ que tenho cadastrado: <verbatim> +----------------------------------------------------+ | Lista Todas as Músicas de um Determinado Artista | | ----- ----- -- ------- -- -- ----------- ------- | | | | Informe o Artista: Emerson, Lake & Palmer | +----------------------------------------------------+ | | | Jerusalem | | Toccata | | Still ... You Turn Me On | | Benny The Bouncer | | Karn Evil 9 | | | +-----------Tecle Algo para Nova Consulta------------+ </verbatim> ---++ Envenenando a escrita - Ufa! Agora você já sabe tudo sobre leitura, mas sobre escrita está apenas engatinhando. Já sei que você vai me perguntar:%BR% - Ora, não é com o comando =echo= e com os redirecionamentos de saída que se escreve? É, com estes comandos você escreve 90% das coisas necessárias, porém se precisar de escrever algo formatado eles lhe darão muito trabalho. Para formatar a saída veremos agora uma instrução muito interessante - é o =printf= - sua sintaxe é a seguinte: <verbatim> printf formato [argumento...] </verbatim> Onde:%BR% =formato= - é uma cadeia de caracteres que contem 3 tipos de objeto: 1. caracteres simples; 1. caracteres para especificação de formato; 1. seqüência de escape no padrão da linguagem C.%BR% =Argumento= - é a cadeia a ser impressa sob o controle do =formato=. Cada um dos caracteres utilizados para especificação de =formato= é precedido pelo caracter =%= e logo a seguir vem a especificação de =formato= de acordo com a tabela: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Tabela dos Caracteres de Formatação do printf* || | *Letra* | *A expressão será impressa como:* | | =c= | Simples caractere | | =d= | Número no sistema decimal | | =e= | Notação científica exponencial | | =f= | Número com ponto decimal (_float_) | | =g= |O menor entre os formatos =%e= e =%f= com supressão dos zeros não significativos | | =o= | Número no sistema octal | | =s= | Cadeia de caracteres | | =x= | Número no sistema hexadecimal | | =%= | Imprime um =%=. Não existe nenhuma conversão | </center> As seqüências de _escape_ padrão da linguagem C são sempre precedidas por um contra-barra (=\=) e as reconhecidas pelo comando =printf= são: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Sequencias de _Escape_ do printf* || | *Seqüência* | *Efeito* | | =a= | Soa o beep | | =b= | Volta uma posição (_backspace_) | | =f= | Salta para a próxima página lógica (_form feed_) | | =n= | Salta para o início da linha seguinte (_line feed_) | | =r= | Volta para o início da linha corrente (_carriage return_) | | =t= | Avança para a próxima marca de tabulação | </center> Não acabou por aí não! Tem muito mais coisa sobre a instrução, mas como é muito cheio de detalhes e, portanto, chato para explicar e, pior ainda para ler ou estudar, vamos passar direto aos exemplos com seus comentários, que não estou aqui para encher o saco de ninguém. %TERMINAL_INI% $ printf "%c" "1 caracter"%OUT_INI% 1%OUT_FIM%$ %T2%Errado! Só listou 1 caractere e não saltou linha ao final%T0% $ printf "%c\n" "1 caracter"%OUT_INI% 1%OUT_FIM% %T2%Saltou linha mas ainda não listou a cadeia inteira%T0% $ printf "%c caractere\n" 1%OUT_INI% 1 caractere%OUT_FIM% %T2%Esta é a forma correta o %c recebeu o 1%T0% $ a=2 $ printf "%c caracteres\n" $a%OUT_INI% 2 caracteres%OUT_FIM% %T2%O %c recebeu o valor da variável $a%T0% $ printf "%10c caracteres\n" $a%OUT_INI% 2 caracteres%OUT_FIM% $ printf "%10c\n" $a caracteres%OUT_INI% 2 c%OUT_FIM% %TERMINAL_FIM% Repare que nos dois últimos exemplos, em virtude do =%c=, só foi listado um caracter de cada cadeia. O =10= à frente do =c=, não significa 10 caracteres. Um número seguindo o sinal de percentagem (=%=) significa o tamanho que a cadeia terá após a execução do comando. E tome de exemplo: %TERMINAL_INI% $ printf "%d\n" 32%OUT_INI% 32%OUT_FIM% $ printf "%10d\n" 32%OUT_INI% 32%OUT_FIM% %T2%Preenche com brancos à esquerda e não com zeros%T0% $ printf "%04d\n" 32%OUT_INI% 0032%OUT_FIM% %T2%04 após % significa 4 dígitos com zeros à esquerda%T0% $ printf "%e\n" $(echo "scale=2 ; 100/6" | bc)%OUT_INI% 1.666000e+01%OUT_FIM% %T2%O default do %e é 6 decimais%T0% $ printf "%.2e\n" `echo "scale=2 ; 100/6" | bc`%OUT_INI% 1.67e+01%OUT_FIM% %T2%O .2 especificou duas decimais%T0% $ printf "%f\n" 32.3%OUT_INI% 32.300000%OUT_FIM% %T2%O default do %f é 6 decimais%T0% $ printf "%.2f\n" 32.3%OUT_INI% 32.30%OUT_FIM% %T2%O .2 especificou duas decimais%T0% $ printf "%.3f\n" `echo "scale=2 ; 100/6" | bc`%OUT_INI% 33.330%OUT_FIM% %T2%O bc devolveu 2 decimais. o printf colocou 0 à direita%T0% $ printf "%o\n" 10%OUT_INI% 12%OUT_FIM% %T2%Converteu o 10 para octal%T0% $ printf "%03o\n" 27%OUT_INI% 033%OUT_FIM% %T2%Assim a conversão fica com mais jeito de octal, né?%T0% $ printf "%s\n" Peteleca%OUT_INI% Peteleca%OUT_FIM% $ printf "%15s\n" Peteleca%OUT_INI% Peteleca%OUT_FIM% %T2%Peteleca com 15 caracteres enchidos com brancos%T0% $ printf "%-15sNeves\n" Peteleca%OUT_INI% Peteleca Neves%OUT_FIM% %T2%O menos (-) encheu à direita com brancos%T0% $ printf "%.3s\n" Peteleca%OUT_INI% Pet%OUT_FIM% %T2%3 trunca as 3 primeiras%T0% $ printf "%10.3sa\n" Peteleca%OUT_INI% Peta%OUT_FIM% %T2%Pet com 10 caracteres concatenado com a (após o s)%T0% $ printf "EXEMPLO %x\n" 45232%OUT_INI% EXEMPLO b0b0%OUT_FIM% %T2%Transformou para hexa mas os zeros não combinam%T0% $ printf "EXEMPLO %X\n" 45232%OUT_INI% EXEMPLO B0B0%OUT_FIM% %T2%Assim disfarçou melhor (repare o X maiúsculo)%T0% $ printf "%X %XL%X\n" 49354 192 10%OUT_INI% C0CA C0LA%OUT_FIM% %TERMINAL_FIM% O último exemplo não é _marketing_ e é bastante completo, vou comentá-lo passo-a-passo: 1. O primeiro =%X= converteu =49354= em hexadecimal resultando =C0CA= (leia-se "cê", "zero", "cê" e "a"); 1. Em seguida veio um espaço em branco seguido por outro =%XL=. O =%X= converteu o =192= dando como resultado =C0= que com o =L= fez =C0L=; 1. E finalmente o último =%X= transformou o =10= em =A=. Conforme vocês podem notar, a instrução =printf= é bastante completa e complexa (ainda bem que o =echo= resolve quase tudo). Creio que quando resolvi explicar o =printf= através de exemplos, acertei em cheio pois não saberia como enumerar tantas regrinhas sem tornar a leitura enfadonha. ---++ Principais Variáveis do _Shell_ O _Bash_ possui diversas variáveis que servem para dar informações sobre o ambiente ou alterá-lo. Seu número é muito grande e não pretendo mostrar todas, mas uma pequena parte que pode lhe ajudar na elaboração de _scripts_. Então aí vão as principais: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Principais variáveis do Bash* || | *Variável* |<nop> *Conteúdo* | | CDPATH | Contém os caminhos que serão pesquisados para tentar localizar um diretório especificado. Apesar desta variável ser pouco conhecida, seu uso deve ser incentivado por poupar muito trabalho, principalmente em instalações com estrutura de diretórios com bastante níveis. | | HISTSIZE | Limita o número de instruções que cabem dentro do arquivo de histórico de comandos (normalmente =.bash_history= mas efetivamente é o que está armazenado na variável =$HISTFILE=). Seu valor _default_ é 500. | | HOSTNAME | O nome do host corrente (que também pode ser obtido com o comando =uname -n=). | | LANG | Usada para determinar a língua falada no pais (mais especificamente categoria do locale). | | LINENO | O número da linha do _script_ ou da função que está sendo executada, seu uso principal é para dar mensagens de erro juntamente com as variáveis =$0= (nome do programa) e =$FUNCNAME= (nome da função em execução) | | LOGNAME | Armazena o nome de _login_ do usuário. | | MAILCHECK | Especifica, em segundos, a freqüência que o Shell verificará a presença de correspondências nos arquivos indicados pela variáveis =$MAILPATH= ou =$MAIL=. O tempo padrão é 60 segundos. Uma vez este tempo expirado, o _Shell_ fará esta verificação antes de exibir o próximo _prompt_ primário (definido em =$PS1=). Se esta variável estiver sem valor ou com um valor menor ou igual a zero, a verificação de novas correspondências não será efetuada. | | PATH | Caminhos que serão pesquisados para tentar localizar um arquivo especificado. Como cada _script_ é um arquivo, caso use o diretório corrente (=.=) na sua variável =$PATH=, você não necessitará de usar o =./scrp= para que =scrp= seja executado. Basta fazer =scrp=. Este é o modo que procedo aqui no Botequim. | | PIPESTATUS | É uma variável do tipo vetor (_array_) que contém uma lista valores de código de retorno do último _pipeline_ executado, isto é, um _array_ que abriga cada um dos =$?= de cada instrução do último _pipeline_. | | PROMPT_COMMAND | Se esta variável receber uma instrução, toda vez que você der um =<ENTER>= direto no prompt principal (=$PS1=), este comando será executado. É útil quando se está repetindo muito uma determinada instrução. | | PS1 | É o _prompt_ principal. No "Papo de Botequim" usamos os seus _defaults_: =$= para usuário comum e =#= para _root_, mas é muito freqüente que ele esteja customizado. Uma curiosidade é que existe até concurso de quem programa o =$PS1= mais criativo. <a href="http://www.google.com.br/search?num=100&hl=pt-BR&q=+%22PS1%22++Linux++prompt+personalizar+alterar&btnG=Pesquisar&meta=cr=countryBR" target="_blank">(clique para dar uma googlada)</a> | | PS2 | Também chamado _prompt_ de continuação, é aquele sinal de maior (=>=) que aparece após um =<ENTER>= sem o comando ter sido encerrado. | | PWD | Possui o caminho completo (=$PATH=) do diretório corrente. Tem o mesmo efeito do comando =pwd=. | | RANDOM | Cada vez que esta variável é acessada, devolve um número inteiro, que é um randômico entre 0 e 32767. | | REPLY | Use esta variável para recuperar o último campo lido, caso ele não tenha nenhuma variável associada. | | SECONDS | Esta variável contém a quantidade de segundos que o _Shell_ corrente está de pé. Use-a somente para esnobar um usuários daquilo que chamam de sistema operacional, mas necessita de _boots_ freqüentes. :) | | TMOUT | Se tiver um valor maior do que zero, este valor será tomado como o padrão de _timeout_ do comando =read=. No _prompt_, este valor é interpretado como o tempo de espera por uma ação antes de expirar a sessão. Supondo que a variável contenha 30, o _Shell_ dará _logout_ após 30 segundos de _prompt_ sem nenhuma ação. | </center> * *CDPATH* %TERMINAL_INI% $ echo $CDPATH%OUT_INI% .:..:~:/usr/local%OUT_FIM% $ pwd%OUT_INI% /home/jneves/LM%OUT_FIM% $ cd bin $ pwd%OUT_INI% /usr/local/bin%OUT_FIM% %TERMINAL_FIM% Como /usr/local estava na minha variável =$CDPATH=, e não existia o diretório =bin= em nenhum dos seus antecessores (=.=, =..= e =~=), o =cd= foi executado para =/usr/local/bin= * *LANG* %TERMINAL_INI% $ date%OUT_INI% Thu Apr 14 11:54:13 BRT 2005%OUT_FIM% $ LANG=pt_BR date%OUT_INI% Qui Abr 14 11:55:14 BRT 2005%OUT_FIM% %TERMINAL_FIM% Com a especificação da variável =LANG=pt_BR= (português do Brasil), a data passou a ser informada no padrão brasileiro. É interessante observarmos que não foi usado ponto-e-vírgula (=;=) para separar a atribuição de =LANG= do comando =date=. * *PIPESTATUS* %TERMINAL_INI% $ who%OUT_INI% jneves pts/0 Apr 11 16:26 (10.2.4.144) jneves pts/1 Apr 12 12:04 (10.2.4.144)%OUT_FIM% $ who | grep ^botelho $ echo ${PIPESTATUS[*]}%OUT_INI% 0 1%OUT_FIM% %TERMINAL_FIM% Neste exemplo mostramos que o usuário =botelho= não estava "logado", em seguida executamos um _pipeline_ que procurava por ele. Usa-se a notação =[*]= em um _array_ para listar todos os seus elementos, e desta forma vimos que a primeira instrução (=who=) foi bem sucedida (código de retorno 0) e a seguinte (=grep=), não (código de retorno 1). * *RANDOM* Para gerar randomicamente um inteiro entre 0 e 100, fazemos: %TERMINAL_INI% $ echo $((RANDOM%101))%OUT_INI% 73%OUT_FIM% %TERMINAL_FIM% Ou seja pegamos o resto da divisão por =101= do número randômico gerado, porque o resto da divisão de qualquer número por 101 varia entre 0 e 100. * *REPLY* %TERMINAL_INI% $ read -p "Digite S ou N: "%OUT_INI% Digite S ou N:%OUT_FIM% N $ echo $REPLY%OUT_INI% N%OUT_FIM% %TERMINAL_FIM% Eu sou do tempo que memória era um bem precioso que custava muuuuito caro. Então para pegar um =S= ou um =N=, não costumo a alocar um espaço especial e assim sendo, pego o que foi digitado na variável =$REPLY=. ---++ Expansão de parâmetros Bem, muito do que vimos até agora são comandos externos ao _Shell_. Eles quebram o maior galho, facilitam a visualização, manutenção e depuração do código, mas não são tão eficientes quanto os intrínsecos (_built-ins_). Quando o nosso problema for performance, devemos dar preferência ao uso dos intrínsecos e a partir de agora vou te mostrar algumas técnicas para o teu programa pisar no acelerador. Na tabela e exemplos a seguir, veremos uma série de construções chamadas expansão (ou substituição) de parâmetros (_Parameter Expansion_), que substituem instruções como o =cut=, o =expr=, o =tr=, o =sed= e outras de forma mais ágil. <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Expansão de parâmetros* || | *Expressão* | *Resultado esperado* | | =${var:-padrao}= | Se =var= não tem valor, o resultado da expressão é =padrao= | | =${#cadeia}= | Tamanho de =$cadeia= | | =${cadeia:posicao}= | Extrai uma subcadeia de =$cadeia= a partir de =posicao=. Origem zero | | =${cadeia:posicao:tamanho}= | Extrai uma subcadeia de =$cadeia= a partir de =posicao= com tamanho igual a =tamanho=. Origem zero | | =${cadeia#expr}= | Corta a menor ocorrência de =$cadeia= à esquerda da expressão =expr= | | =${cadeia##expr}= | Corta a maior ocorrência de =$cadeia= à esquerda da expressão =expr= | | =${cadeia%expr}= | Corta a menor ocorrência de =$cadeia= à direita da expressão =expr= | | =${cadeia%%expr}= | Corta a maior ocorrência de =$cadeia= à direita da expressão =expr= | | =${cadeia/subcad1/subcad2}= | Troca em =$cadeia= a primeira ocorrência de =subcad1= por =subcad2= | | =${cadeia//subcad1/subcad2}= | Troca em =$cadeia= todas as ocorrências de =subcad1= por =subcad2= | | =${cadeia/#subcad1/subcad2}= | Se =subcad1= combina com o início de =$cadeia=, então é trocado por =subcad2= | | =${cadeia/%subcad1/subcad2}= | Se =subcad1= combina com o fim de =$cadeia=, então é trocado por =subcad2= | </center> * Se em uma pergunta o =S= é oferecido como valor _default_ (padrão) e a saída vai para a variável =$SN=, após ler o valor podemos fazer: <verbatim> SN=$(SN:-S} </verbatim> Desta forma se o operador deu um simples =<ENTER>= para confirmar que aceitou o valor _default_, após executar esta instrução, a variável terá o valor =S=, caso contrário, terá o valor digitado. * Para sabermos o tamanho de uma cadeia: %TERMINAL_INI% $ cadeia=0123 $ echo ${#cadeia}%OUT_INI% 4%OUT_FIM% %TERMINAL_FIM% * Para extrair de uma cadeia da posição um até o final fazemos: %TERMINAL_INI% $ cadeia=abcdef $ echo ${cadeia:1}%OUT_INI% bcdef%OUT_FIM% %TERMINAL_FIM% Repare que a origem é zero e não um. * Na mesma variável =$cadeia= do exemplo acima, para extrair 3 caracteres a partir da 2ª posição: %TERMINAL_INI% $ echo ${cadeia:2:3}%OUT_INI% cde%OUT_FIM% %TERMINAL_FIM% Repare que novamente que a origem da contagem é zero e não um. * Para suprimir tudo à esquerda da primeira ocorrência de uma cadeia, faça: %TERMINAL_INI% $ cadeia="Papo de Botequim" $ echo ${cadeia#*' '}%OUT_INI% de Botequim%OUT_FIM% $ echo "Conversa "${cadeia#*' '}%OUT_INI% Conversa de Botequim%OUT_FIM% %TERMINAL_FIM% Neste exemplo foi suprimido à esquerda tudo que casasse com a menor ocorrência da expressão =*' '=, ou seja, tudo até o primeiro espaço em branco. Estes exemplos também poderiam ser escritos sem protegermos o espaço da interpretação do Shell (mas prefiro protegê-lo para facilitar a legibilidade do código), veja: %TERMINAL_INI% $ echo ${cadeia#* }%OUT_INI% de Botequim%OUT_FIM% $ echo "Conversa "${cadeia#* }%OUT_INI% Conversa de Botequim%OUT_FIM% %TERMINAL_FIM% Repare que na construção de =expr= é permitido o uso de metacaracteres. * Utilizando o mesmo valor da variável =$cadeia=, observe como faríamos para termos somente =Botequim=: %TERMINAL_INI% $ echo ${cadeia##*' '}%OUT_INI% Botequim%OUT_FIM% $ echo "Vamos 'Chopear' no "${cadeia##*' '}%OUT_INI% Vamos 'Chopear' no Botequim%OUT_FIM% %TERMINAL_FIM% Desta vez suprimimos à esquerda de cadeia a maior ocorrência da expressão =expr=. Assim como no caso anterior, o uso de metacaracteres é permitido. Outro exemplo mais útil: para que não apareça o caminho (_path_) completo do seu programa (que, como já sabemos está contido na variável =$0=) em uma mensagem de erro, inicie o seu texto da seguinte forma: <verbatim> echo Uso: ${0##*/} texto da mensagem de erro </verbatim> Neste exemplo seria suprimido à esquerda tudo até a última barra (=/=) do caminho (_path_), desta forma sobrando somente o nome do programa. * O uso do percentual (=%=) é como se olhássemos o jogo-da-velha (=#=) no espelho, isto é, são simétricos. Então vejamos um exemplo para provar isso: %TERMINAL_INI% $ echo $cadeia%OUT_INI% Papo de Botequim%OUT_FIM% $ echo ${cadeia%' '*}%OUT_INI% Papo de%OUT_FIM% $ echo ${cadeia%%' '*}%OUT_INI% Papo%OUT_FIM% %TERMINAL_FIM% * Para trocar primeira ocorrência de uma subcadeia em uma cadeia por outra: %TERMINAL_INI% $ echo $cadeia%OUT_INI% Papo de Botequim%OUT_FIM% $ echo ${cadeia/de/no}%OUT_INI% Papo no Botequim%OUT_FIM% $ echo ${cadeia/de /}%OUT_INI% Papo Botequim%OUT_FIM% %TERMINAL_FIM% Neste caso preste a atenção quando for usar metacaracteres, eles são gulosos! Eles sempre combinarão com a maior possibilidade, veja o exemplo a seguir onde a intenção era trocar =Papo de Botequim= por =Conversa de Botequim=: %TERMINAL_INI% $ echo $cadeia%OUT_INI% Papo de Botequim%OUT_FIM% $ echo ${cadeia/*o/Conversa}%OUT_INI% Conversatequim%OUT_FIM% %TERMINAL_FIM% A idéia era pegar tudo até o primeiro =o=, mas o que foi trocado foi tudo até o último =o=. Isto poderia ser resolvido de diversas maneiras, veja algumas: %TERMINAL_INI% $ echo ${cadeia/*po/Conversa}%OUT_INI% Conversa de Botequim%OUT_FIM% $ echo ${cadeia/????/Conversa}%OUT_INI% Conversa de Botequim%OUT_FIM% %TERMINAL_FIM% * Trocando todas as ocorrências de uma subcadeia por outra. Quando fazemos: %TERMINAL_INI% $ echo ${cadeia//o/a}%OUT_INI% Papa de Batequim%OUT_FIM% %TERMINAL_FIM% Trocamos todos as letras =o= por =a=. Outro exemplo mais útil é para contarmos a quantidade de arquivos existentes no diretório corrente. Observe a linha a seguir: %TERMINAL_INI% $ ls | wc -l%OUT_INI% 30%OUT_FIM% %TERMINAL_FIM% Viu? O =wc= produz um monte de espaços em branco no início. Para tirá-los podemos fazer: %TERMINAL_INI% $ <nop>QtdArqs=$(ls | wc -l) # <nop>QtdArqs recebe a saída do comando $ echo ${QtdArqs// /}%OUT_INI% 30%OUT_FIM% %TERMINAL_FIM% No último exemplo, como eu sabia que a saída era composta de brancos e números, montei esta expressão para trocar todos os espaços por nada. Repare que após as duas primeiras barras existe um espaço em branco. Outra forma de fazer a mesma coisa seria: %TERMINAL_INI% $ echo ${QtdArqs/* /}%OUT_INI% 30%OUT_FIM% %TERMINAL_FIM% * Trocando uma subcadeia no início ou no fim de uma variável. Para trocar no início fazemos: %TERMINAL_INI% $ echo $Passaro%OUT_INI% quero quero%OUT_FIM% $ echo "Como diz o sulista - "${Passaro/#quero/não}%OUT_INI% Como diz o sulista - não quero%OUT_FIM% %TERMINAL_FIM% Para trocar no final fazemos: %TERMINAL_INI% $ echo "Como diz o nordestino - "${Passaro/%quero/não}%OUT_INI% Como diz o nordestino - quero não%OUT_FIM% %TERMINAL_FIM% - Agora já chega, o papo hoje foi muito chato porque foi muita decoreba, mas o principal é você ter entendido o que te falei e, quando precisar, consulte estes guardanapos em que rabisquei estas dicas e depois guarde-os para consultas futuras. Mas voltando à vaca fria: tá na hora de tomar outro e ver o jogo do mengão. Na próxima vou te dar moleza e só vou cobrar o seguinte: pegue a rotina =pergunta.func=, (a que na qual falamos no início do nosso bate papo de hoje) e otimize-a para que a variável =$SN= receba o valor _default_ por expansão de parâmetros, como vimos. - Chico, vê se não esquece de mim e enche meu copo. 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
: r13
<
r12
<
r11
<
r10
<
r9
|
B
acklinks
|
V
iew topic
|
M
ore topic actions
Topic revision: r13 - 01 Aug 2009 - 22:33:48 -
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