Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Shell Scripting: Formatação de Cadeias de Caracteres e Expansão de Parâmetros, Notas de estudo de Informática

Neste artigo do papo de botequim, publicado na edição 09 de junho de 2005 da linux magazine br, júlio cezar neves aborda as mensagens de erro e as perguntas feitas ao usuário no shell script. Ele explica como mostrar mensagens personalizadas na tela usando a função printf e as principais variáveis do shell. Além disso, o autor aborda o tema da expansão de parâmetros, mostrando como substituir subcadeias em uma cadeia e cortar partes de uma cadeia de acordo com expressões. O artigo também inclui exemplos práticos.

Tipologia: Notas de estudo

2011

Compartilhado em 10/03/2011

william-felipe-dutra-abreu-da-silva
william-felipe-dutra-abreu-da-silva 🇧🇷

21 documentos

1 / 6

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Tá bom, já sei que você vai querer chope antes de começar,
mas tô tão a fi m de te mostrar o que z que já vou pedir a
rodada enquanto isso. Aê Chico, manda dois! O dele é sem
colarinho pra não deixar cheiro ruim nesse bigodão…
Enqua nto o chope não chega, deixa eu te lembrar o que
você me pediu na edição passada: era para refazer
o programa list artista com a tela formatada e exe-
cução em loop, de forma que ele só term ine quando
receber um [ENTER ] sozinho como nome do art ista.
Eventuais mensagen s de erro e perguntas feitas ao
usuário deveriam ser mostradas na antepenú ltima
linha da tela, uti lizando para isso as rotinas externas
mandamsg.func e pergunta.func que desenvolvemos
durante nosso papo na edição passada.
Primeiramente eu dei uma encolhida nas rotinas
mandamsg.func e pergunta.func, que fi cara m como
na li sta gem 1. E na l ista gem 2 você tem o “grandão”,
nossa versão refeita do listaartista.
– Puxa, você chegou com a corda toda! Gostei da
forma como você resolveu o problema e estr uturou
o programa. Foi mais trabalhoso, mas a apresenta-
ção cou muito legal e você explorou basta nte a s
opções do comando tput. Vamos testar o resultado
com u m álbum do Emerson, Lake & Palme r que
tenho c adastrado.
Envenenando a escrita
Ufa! Agora você já sabe tudo sobre leitura de dados,
mas quanto à escrita ainda está apenas engatinhando.
Já sei que você vai me perguntar: “Ora, não é com o
comando echo e com os redirecionamentos de saída
que se escreve dados?”.
Bom, a resposta é "mais ou menos". Com estes comandos
você escreve 90% do que precisa, porém se precisar escrever
algo formatado eles lhe darão muito trabalho. Para formatar a
saída veremos agora uma instr ução muito mais interessante,
a printf. Sua sintaxe é a seguinte:
Hoje vamos aprender mais sobre formatação de cadeias de caracteres,
conhecer as principais variáveis do Shell e nos aventurar no (ainda)
desconhecido território da expansão de parâmetros. E dá-lhe chope!
por Júlio Cezar Neves
Curso de Shell Script
Papo de Botequim
Parte IX
Dave Hamilt on - www.sxc.hu
Listagem 1: mandamsg.func e pergunta.func
mandamsg.func
01 # A função recebe somente um parâmetro
02 # com a mensagem que se deseja exibir.
03 # Para não obrigar o programador a passar
04 # a msg entre aspas, usaremos $* (todos
05 # os parâmetro, lembra?) e não $1.
06 Msg="$*"
07 TamMsg=${#Msg}
08 Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha
09 tput cup $LinhaMesg $Col
10 read -n1 -p "$Msg "
pergunta.func
01 # A função recebe 3 parâmetros na seguinte ordem:
02 # $1 - Mensagem a ser mostrada na tela
03 # $2 - Valor a ser aceito com resposta padrão
04 # $3 - O outro valor aceito
05 # Supondo que $1=Aceita?, $2=s e $3=n, a linha
06 # abaixo colocaria em Msg o valor "Aceita? (S/n)"
07 Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)"
08 TamMsg=${#Msg}
09 Col=$(((TotCols - TamMsg) / 2)) # Centraliza msg na linha
10 tput cup $LinhaMesg $Col
11 read -n1 -p "$Msg " SN
12 [ ! $SN ] && SN=$2 # Se vazia coloca default em SN
13 SN=$(echo $SN | tr A-Z a-z) # A saída de SN será em minúscula
14 tput cup $LinhaMesg $Col; tput el # Apaga msg da tela
Linux User
84
Papo de Botequim
www.linu xmagazine.com .br
junho 2005 edição 09
pf3
pf4
pf5

Pré-visualização parcial do texto

Baixe Shell Scripting: Formatação de Cadeias de Caracteres e Expansão de Parâmetros e outras Notas de estudo em PDF para Informática, somente na Docsity!

T

á bom, já sei que você vai querer chope antes de começar, mas tô tão a fi m de te mostrar o que fi z que já vou pedir a rodada enquanto isso. Aê Chico, manda dois! O dele é sem colarinho pra não deixar cheiro ruim nesse bigodão… Enquanto o chope não chega, deixa eu te lembrar o que você me pediu na edição passada: era para refazer o programa listartista com a tela formatada e exe- cução em loop, de forma que ele só termine quando receber um [ENTER] sozinho como nome do artista. Eventuais mensagens de erro e perguntas feitas ao usuário deveriam ser mostradas na antepenúltima linha da tela, utilizando para isso as rotinas externas mandamsg.func e pergunta.func que desenvolvemos durante nosso papo na edição passada. Primeiramente eu dei uma encolhida nas rotinas mandamsg.func e pergunta.func , que ficaram como na listagem 1. E na listagem 2 você tem o “grandão”, nossa versão refeita do listaartista.

  • Puxa, você chegou com a corda toda! Gostei da forma como você resolveu o problema e estruturou o programa. Foi mais trabalhoso, mas a apresenta- ção ficou muito legal e você explorou bastante as opções do comando tput. Vamos testar o resultado com um álbum do Emerson, Lake & Palmer que tenho cadastrado.

Envenenando a escrita

Ufa! Agora você já sabe tudo sobre leitura de dados, mas quanto à escrita ainda está apenas engatinhando. Já sei que você vai me perguntar: “Ora, não é com o comando echo e com os redirecionamentos de saída que se escreve dados?”. Bom, a resposta é "mais ou menos". Com estes comandos você escreve 90% do que precisa, porém se precisar escrever algo formatado eles lhe darão muito trabalho. Para formatar a saída veremos agora uma instrução muito mais interessante, a printf. Sua sintaxe é a seguinte:

Hoje vamos aprender mais sobre formatação de cadeias de caracteres,

conhecer as principais variáveis do Shell e nos aventurar no (ainda)

desconhecido território da expansão de parâmetros. E dá-lhe chope!

por Júlio Cezar Neves

Curso de Shell Script

Papo de Botequim

Parte IX

Dave Hamilton - www.sxc.hu Listagem 1: mandamsg.func e pergunta.func

mandamsg.func

01 # A função recebe somente um parâmetro 02 # com a mensagem que se deseja exibir. 03 # Para não obrigar o programador a passar 04 # a msg entre aspas, usaremos $ (todos 05 # os parâmetro, lembra?) e não $1. 06 Msg="$" 07 TamMsg=${#Msg} 08 Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha 09 tput cup $LinhaMesg $Col 10 read -n1 -p "$Msg "**

pergunta.func

01 # A função recebe 3 parâmetros na seguinte ordem: 02 # $1 - Mensagem a ser mostrada na tela 03 # $2 - Valor a ser aceito com resposta padrão 04 # $3 - O outro valor aceito 05 # Supondo que $1=Aceita?, $2=s e $3=n, a linha 06 # abaixo colocaria em Msg o valor "Aceita? (S/n)" 07 Msg="$1 (echo $2 | tr a-z A-Z/echo $3 | tr A-Z a-z)" 08 TamMsg=${#Msg} 09 Col=$(((TotCols - TamMsg) / 2)) # Centraliza msg na linha 10 tput cup $LinhaMesg $Col 11 read -n1 -p "$Msg " SN 12 [! $SN ] && SN=$2 # Se vazia coloca default em SN 13 SN=$(echo $SN | tr A-Z a-z) # A saída de SN será em minúscula 14 tput cup $LinhaMesg $Col; tput el # Apaga msg da tela

Linux User

Papo de Botequim

junho 2005 edição 09

printf formato [argumento...] Onde formato é uma cadeia de caracteres que contém três tipos de objeto: caracteres simples, caracteres para es- pecificação de formato (ou de controle ) e seqüência de esca- pe no padrão da linguagem C. argumento é a cadeia de caracteres a ser impressa sob o controle de formato. Cada um dos caracteres uti- lizados é precedido pelo ca- racter % e, logo a seguir, vem a especificação de formato de acordo com a tabela 1. As seqüências de escape padrão da linguagem C são sempre precedidas pelo ca- ractere contra-barra ( ** ). As reconhecidas pelo comando printf são as da tabela 2. Não acaba por aí não! Tem muito mais coisa sobre essa instrução, mas como esse é um assunto muito cheio de detalhes e, portanto, chato para explicar e pior ainda para ler ou estudar, vamos passar direto aos exemplos com co- mentários. Veja só: $ printf "%c" "1 caracter" 1$ Errado! Só listou 1 caractere e não saltou linha ao final $ printf "%c\n" "1 caracter" 1 Saltou linha mas ainda não listou a cadeia inteira $ printf "%c caractere\n" 1

1 caractere ➟

**Listagem 2: listaartista $ cat listartista3.sh 01 #!/bin/bash 02 # Dado um artista, mostra as suas musicas 03 # versao 3 04 LinhaMesg=$((tput lines - 3)) # Linha onde as msgs serão mostradas 05 TotCols=$(tput cols) # Qtd de colunas na tela para enquadrar msgs 06 clear 07 echo " +–––––––––––––––––-----------------------------------+ | Lista Todas as Músicas de um Determinado Artista | | ===== ===== == ======= == == =========== ======= | | | | Informe o Artista: | +––––––––––––––––----------------------------------–-+" 08 while true 09 do 10 tput cup 5 51; tput ech 31 # ech=Erase chars (31 para não apagar barra vertical) 11 read Nome 12 if [! "$Nome" ] # $Nome esta vazio? 13 then

  1. pergunta.func "Deseja Sair?" s n 15 [ $SN = n ] && continue 16 break 17 fi 18 fgrep -iq "^$Nome~" musicas || # fgrep não interpreta ^ como expressão regular 19 {
  2. mandamsg.func "Não existe música desse artista" 21 continue 22 } 23 tput cup 7 29; echo '| |' 24 LinAtual= 25 IFS=" 26 :" 27 for ArtMus in $(cut -f2 -d^ musicas) # Exclui nome do album 28 do 29 if echo "$ArtMus" | grep -iq "^$Nome~" 30 then 31 tput cup $LinAtual 29 32 echo -n '| " 33 echo $ArtMus | cut -f2 -d~ 34 tput cup $LinAtual 82 35 echo '|' 36 let LinAtual++ 37 if [ $LinAtual -eq $LinhaMesg ] 38 then
  3. mandamsg.func "Tecle Algo para Continuar..." 40 tput cup 7 0; tput ed # Apaga a tela a partir da linha 7 41 tput cup 7 29; echo '| |' 42 LinAtual= 43 fi 44 fi 45 done 46 tput cup $LinAtual 29; echo '| |' 47 tput cup $((++LinAtual)) 29 48 read -n1 -p "+–––--Tecle Algo para Nova Consulta––––+" 49 tput cup 7 0; tput ed # Apaga a tela a partir da linha 7 50 done**

junho 2005 edição 09 85

Papo de Botequim Linux User

$ printf “EXEMPLO %x\n” 45232 EXEMPLO b0b Ele transformou o número 45232 para hexadecimal ( b0b0 ), mas os zeros não combinam com o resto. Experimente: $ printf “EXEMPLO %X\n” 45232 EXEMPLO B0B Assim disfarçou melhor! (repare no X maiúsculo). Pra terminar, que tal o co- mando abaixo: $ printf “%X %XL%X\n” 49354 192 10 C0CA C0LA Este aí não é marketing e é bastante completo, veja só como funciona: O primeiro %X converteu 49354 em he- xadecimal, resultando em C0CA (leia-se “cê”, “zero”, “cê” e “a”). 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. E final- mente o último parâmetro %X transformou o número 10 na letra A. Conforme vocês podem notar, a instru- ção é bastante completa e complexa. Ain- da bem que o echo resolve quase tudo... Acertei em cheio quando resolvi expli- car o printf através de exemplos, pois não saberia como enumerar tantas regri- nhas 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. São muitas e não pretendo mostrar todas elas, mas uma pequena parte pode lhe ajudar na elaboração de scripts. Veja a seguir as principais delas: CDPATH » Contém os caminhos que serão pesquisados para tentar localizar um diretório especificado. Apesar dessa variável ser pouco conhecida, seu uso deve ser incentivado por poupar muito trabalho, principalmente em instalações com estrutura de diretórios em múltiplos níveis. Veja o exemplo a seguir: $ echo $CDPATH .:..:~:/usr/local $ pwd /home/jneves/LM $ cd bin $ pwd /usr/local/bin Como /usr/local estava na minha variável $CDPATH e não existia o diretório bin em nenhum dos seus antecessores (. , .. e ~ ), o comando cd foi executado tendo como destino /usr/local/bin. HISTSIZE » Limita o número de ins- truções que cabem dentro do arquivo de histórico de comandos (normalmente .bash_history , mas na verdade é o que está indicado na variável $HISTFILE ). Seu valor padrão é 500. HOSTNAME » O nome do host corrente (que também pode ser obtido com o co- mando uname -n ). LANG » Usada para determinar o idioma falado no país (mais especificamente ca- tegoria do locale ). Veja um exemplo: $ date Thu Apr 14 11:54:13 BRT 2005 $ LANG=pt_BR date Qui Abr 14 11:55:14 BRT 2005 LINENO » O número da linha do script ou função que está sendo executada. Seu uso principal é mostrar mensagens de erro juntamente com as variáveis $ (nome do programa) e $FUNCNAME (nome da função em execução). LOGNAME » Esta variável armazena o nome de login do usuário. MAILCHECK » Especifica, em segundos, a freqüência com que o Shell verifica a pre- sença de correspondência nos arquivos indicados pela variáveis $MAILPATH ou $MAIL. O tempo padrão é de 60 segundos (1 minuto). A cada intervalo o Shell fará a verificação antes de exibir o próximo prompt primário ( $PS1 ). Se essa variável estiver sem valor ou com um valor menor ou igual a zero, a busca por novas men- sagens não será efetuada. PATH » Caminhos que serão pesquisa- dos para tentar localizar um arquivo espe- cificado. Como cada script é um arquivo, caso use o diretório corrente (. ) na sua variável $PATH , você não necessitará usar o comando ./scrp para que o script scrp seja executado. Basta digitar scrp. Este é o modo que prefiro. PIPESTATUS » É uma variável do tipo vetor ( array ) que contém uma lista de valores de códigos de retorno do último pipeline executado, isto é, um array que abriga cada um dos $? de cada instrução do último pipeline. Para entender melhor, veja o exemplo a seguir: $ who jneves pts/0 Apr 11 16:26 (10.2.4.144) jneves pts/1 Apr 12 12:04 (10.2.4.144) $ who | grep ^botelho $ echo ${PIPESTATUS[]} 0 1 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; dessa forma, vimos que a pri- meira instrução ( who ) foi bem-sucedida (código de retorno 0 ) e a seguinte ( grep ) não (código de retorno 1 ). PROMPT_COMMAND » Se esta variável re- ceber o nome de um comando, toda vez que você teclar um [ENTER] sozinho no prompt principal ( $PS1 ), esse comando será executado. É muito útil quando você precisa repetindo constantemente uma determinada instrução. PS1 » É o prompt principal. No “Papo de Botequim” usamos os padrões $ para usuário comum e # para root, mas é mui-

junho 2005 edição 09 87

Papo de Botequim Linux User

to freqüente que ele esteja personalizado. Uma curiosidade é que existe até concurso de quem programa o $PS1 mais criativo. 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 inteiro aleatório en- tre 0 e 32767. Para gerar um inteiro entre 0 e 100, por exemplo, digitamos: $ echo $((RANDOM%101)) 73 Ou seja, pegamos o resto da divisão do número randômico gerado por 101 porque o resto da divisão de qualquer número por 101 varia entre 0 e 100. REPLY » Use esta variável para recuperar o último campo lido, caso ele não tenha nenhuma variável associada. Exemplo: $ read -p "Digite S ou N: " Digite S ou N: N $ echo $REPLY N SECONDS » Esta variável informa, em se- gundos, há quanto tempo o Shell corrente está “de pé”. Use-a para demonstrar a estabilidade do Linux e esnobar usuários daquela coisa com janelinhas coloridas que chamam de sistema operacional, mas que necessita de “reboots” freqüentes. TMOUT » Se esta variável contiver um valor maior do que zero, esse valor será considerado o timeout padrão do comando read. No prompt, esse valor é interpretado como o tempo de espera por uma ação antes de expirar a sessão. Supondo que a variável contenha o valor 30 , o Shell encerrará a sessão do usuário (ou seja, fará logout ) após 30 segundos sem nenhuma ação no prompt.

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ínse- cos ( built-ins ). Quando o nosso problema for performance, devemos dar preferência ao uso dos intrínsecos. A partir de agora vou te mostrar algumas técnicas para o seu programa pisar no acelerador. Na tabela 3 e nos exemplos a seguir, veremos uma série de construções cha- madas 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. Vamos ver alguns exemplos: se em uma pergunta o S é oferecido como valor de- fault (padrão) e a saída vai para a variável SN , após ler o valor podemos fazer: SN=$(SN:-S} Para saber o tamanho de uma cadeia : $ cadeia= $ echo ${#cadeia} 4 Para extrair dados de cadeia , da posi- ção um até o final fazemos: $ cadeia=abcdef $ echo ${cadeia:1} bcdef Repare que a origem é zero e não um. Vamos extrair 3 caracteres a partir da 2ª posição da mesma variável cadeia : $ echo ${cadeia:2:3} cde Repare que novamente a origem da con- tagem é zero e não um. Para suprimir tudo à esquerda da primeira ocorrência de uma cadeia, faça: $ cadeia="Papo de Botequim" $ echo ${cadeia#' '} de Botequim $ echo "Conversa "${cadeia#' '} Conversa de Botequim No exemplo anterior foi suprimido à esquerda tudo o que “casa” com a menor ocorrência da expressão ’ ‘ , ou seja, todos os caracteres até o primeiro espaço em branco. Esses exemplos também po- deriam ser escritos sem proteger o espaço da interpretação do Shell (mas prefiro protegê-lo para facilitar a legibilidade do código). Veja só: $ echo ${cadeia# } de Botequim $ echo "Conversa "${cadeia#* } Conversa de Botequim 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 ter somente Botequim : $ echo ${cadeia##' '} Botequim $ echo "Vamos 'Chopear' no "${cadeia##' '} Vamos 'Chopear' no Botequim 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 ( $0 ) em uma mensagem de erro, inicie o seu texto da seguinte forma: echo Uso: ${0##*/} texto da mensagem de erro Neste exemplo seria suprimido à es- querda tudo até a última barra ( / ) do caminho, restando somente o nome do programa. O caractere % é simétrico ao # , veja o exemplo:

Linux User

Papo de Botequim

junho 2005 edição 09