You are on page 1of 75
=> Estacio Disciplina: PROGRAMACAO PARA SERVIDORES Classic Shell Scripting 1a. Edic&o/2008 Arnold Robbins Capitulos - Capitulo 2 - Comegando = Capitulo 3 - Pesquisando e Substituindo Classic . S = Capitulo 5 - Pipelines Podem Fazer Coisas SI II Impressionantes Sito | ae Re wtp) eh ates Bookman http://www, bookman.com.br ISBN 9788577801473 = feet saonreeed parte 1 de 2 Comesando Quando voc? precisa fazer um trabalho com um computador, o melhor ¢ usar uma ferramenta que seja apropriada ao trabalho. Voc€ ngo usa um editor de textos para calcular suas conta, ou uma calculadora para escrever uma proposta. Da mesma forma, diferentes linguagens de programagao vao ao encontro de diferentes necessidades quando se trata de realizar alguma tarefa relacionada a computadores. Sheil scripts séo mais freqlientemente usados para tarefes de administragdo de sistemas ou para combinar programas existentes para concluir um trabalho pequeno e espectfico. Uma vez que voc® descobre como fazer o trabalho, & possivel juntar os comandos em um programa ‘parte, ou scripr, que vocé pode entio executar diretamente. Além disso, se o programa é til, outras pessoas podem fazer uso dele, tratando-o como uma eaixa-preta, um programa que faz o trabalho sem que elas precisem saber como ele o faz. Neste capitulo faremos uma breve comparacdo entre diferentes tipos de linguagens de progra- magi ¢ entiio comegaremos a escrever alguns shell scripts simples. 2.1 LINGUAGENS DE SCRIPT VERSUS LINGUAGENS COMPILADAS ‘A maioria dos programas de médio e grande porte é escrita em uma linguagem compilada como Fortran, Ada, Pascal, C, C++ ou Java. Os programas sao traduzidos de seu cédigo fonte original para 0 cédigo objeto, que pode ser executado diretamente pelo hardware do compu- tador.* A vantagem das Linguagens compiladas ¢ que elas sto eficientes. A desvantagem ¢ que elas normalmente trabalham em baixo nivel, lidando com bytes, inteiros, nimeros de ponto flutu- ante e outros objetos de nivel de méquina. Por exemplo, em C+ € dificil dizer algo simples como “copie todos os arquivos neste diret6rio para aquele diret6rio 1a”. * Essa declaragdo ndo 6 totalmente verdadcia para Jeva, mas 6 préxima o suficiente para fins de discusso, 32__ Classic Shell Scripting 2.2 2.3 A ditas linguagens de script sio geralmente interpretadas. Um programa compilado normal, 0 interpretador, \é 0 programa, o traduz. para um formato interno ¢ 0 executa.* POR QUE UTILIZAR UM SHELL SCRIPT Pelo fato do shell ser universal entre sistemas Unix, e pela linguagem ser padronizada con- forme o padro POSIX, shell scripts podem ser eseritos uma vez e, se escritos com cuidado, uusados através de uma série de sistemas. Assim, as raz5es para usar um shell script so: Simplicidade O shell uma linguagem de alto nivel; vocé pode expressar operagdes complexas de forma clara ¢ simples com ele. Portabilidade Usando apenas funcionalidades de especificagaio POSIX, voce tem boas chances de ser capaz de mover seu script, inalterado, para diferentes tipos de sistemas. Facilidade de desenvolvimento Muitas vezes vocé pode escrever um script poderoso e titil em pouco tempo. UM SCRIPT SIMPLES Vamos comegar com um script simples. Suponha que vocé gostaria de saber quantos usudrios, estio atualmente conectados 20 sistema. O comando who mostra quem esté conectado: $ who george pt s/2 Dec 31 16:39 (valley-forge.example. com) betsy pt s/3 Dec 27.11:07 (flags~r-us. example.con) benjanin dtlocal Dec 27 17:55 _(kites.exanple.con) hancock pts/S Dec 27.17:55 (32) canu pts/s Dec 31 16:22 tolstoy pts/ié Jan. 2 06:42 Em um sistema multiusudrio grande, a listagem pode causar a rolagem da tela antes que voce possa contar todos 0s usuérios, e isso & um tanto desagradavel quando acontece a todo mo- mento, Essa é a oportunidade perfeita para a automacao. O que falta é uma forma de contar © nimero de usuérios. Para isso, usamos 0 programa we (Word count), que conta linhas, pala- vras ¢ caracteres. Neste caso, queremos que ove -1, conte apenas linhas: $ who | we -1 Conia usurios 6 O sfmbolo | (pipe) cria um canal entre os dois programas: a safda do who tomna-se a entrada do vc. O resultado, impresso por vc, € 0 mimero de usuérios conectados. O préximo passo é transformar ese canal em um comando separado. Vocé faz isso escrevendo 0s comandos em um arquivo normal e entéo tornando-o executavel, com chmod, da seguinte forma: 9 cat > nusers ria o anqvo, copia a entrada do terminal como cat who | we -1 Teco do programa > Ciri-D €0 mde arquivo ‘Veja em hp ffoldoc doc ic ae.ulffoldoctfoldec.cei?Ousterhous'stichoromy uma tenttiva de formalizar a disiinglo entre Tinguagens interpretadas e compiladas. Esta formatizasio néo € aceta universalmente. CAPITULO 2 * Comesando 33 $ chmod +x ausers Torneo exceuel $./nasers Fara ana exeeugéo de teste 6 Asaida 60 qu esperdvames Este € 0 tipico ciclo de desenvolvimento para pequenos shell scripis de uma ou duas linhas: primeiro, voeé experimenta diretamente na linha de comando; depois, tendo descoberto os encantamentos certos para fazer 0 que quer, vocé 0s coloca em um script separado ¢ tomna-o executével. Voce pode enti usar 0 script desse ponto em diante. 2.4 SCRIPTS AUTOCONTIDOS: A PRIMEIRA LINHA #! Quando o shell executa um programa, ele pede ao kernel Unix para iniciar um novo processo e executar nele 0 programa dado. O kernel sabe como fazer isso para programas compilados. O nosso shell script nusers néo é um programa compilado; quando o shell pedir ao kernel para executé-lo, o kernel niio conseguiré fazer isso, retornando um erro “formato de arquivo no executavel”. O shell, ao receber esse erro, diz. “Aha, esse no é um programa compilado, deve ser um shell script” e entao inicia uma nova c6pia de /rin/st (o shell padrao) para exe- cutar 0 programa, O mecanismo que busca diretamente um determinado shel! funciona muito bem quando hé apenas um shell no sistema. Entretanto, pelo fato das Unix atuais possuirem méhiplos sheits, € preciso haver uma forma de dizer ao kernel Unix qual shelf usar ao executar um shell script especifico. Na verdade, essa necessidade favorece a existéncia de um mecanismo geral que possibilite a invocagio de qualquer interpretador de linguagem de programacio, niio apenas uum shell de comandos. Isso ¢ feito através da primeira linha especial no script que comeca com 0s caracteres #! Quando os dois primeiros caracteres de um arquivo so #!, 0 kemel vasculha o resto da linha em busca do caminho completo de um interpretador para usar na execugo do programa (qualquer espago em branco extra é ignorado). O kernel também procura por uma iinica op- cdo a ser passada para o interpretador. Ele entio invoca o interpretador com a dada opeao ¢ com 0 resto da linha de comando. Por exemplo, considere um script csi* chamado de /usr/ uch/whizprog, com a primeira linha sendo: #1 [oin/esh -t Considere, além disso, que /us+/ucb est inelufdo no caminho de procura do shell (deserito mais adiante). Quando um usuario digita o comando whizprog -q /dev/tty01, 0 kernel inter- preta a linha com #1 ¢ invoca csh da seguinte forma: /bin/osh -£ /usr/uch/whizprog -q /dev/tty01 Esse mecanismo faz com que seja facil inyocar qualquer linguagem interpretada, Ele é uma boa maneira de invocar um programa auténomo em awk: #1 /bin/awk -t programa em cask Shell scripts sao tipicamente iniciados com #! /bin/sh. Use 0 caminho para um shell concor- dante com POSIX se o seu /bin/sh ndo segue o padrio POSIX. Existem também algumas “pegadinhas” de haixo nivel para as quais se deve atentar: ‘/bin/osh € 0 interpretador de comandos C shel, originalmente desenvolvido pela Universidade da CalifOmia em Berkeley. [Nao abordamos programagio C shell neste livro por muitasrez6cs, a mais importante delas ¢ que ele ¢ reconhecidamente pobre para programscao de scripts, além de nio ser paconizado por POSIX. 34__ Classic Shell Scripting ‘+ Em sistemas modernos, 0 tamanho méximo da linha contendo #1 varia de 63 a 1024 caracteres. Tente manté-la com menos de 64 caracteres, (veja a Tabela 2-1 para uma lista representativa de diferentes limites). ‘* Em alguns sistemas, 0 “resto da linha de comando” que € passado ao interpretador inelui © caminho completo do comando. Em outros, isso nao acontece; a linha de comando é passada ao programa da forma como foi digitada. Assim, scripts que olham para 0s ar- gumentos da linha de comando nao podem, de forma portavel, depender da presenga do caminho completo. ‘+ Nao coloque espaco em branco extra depois de uma opeao. Se presente, ele ser passadlo 0 programa invocado junto com a opgio. * Yocé deve saber o caminho completo do interpretador a ser executado, Isso pode prevenit problemas de portabilidade entre empresas, pois diferentes empresas colocam coisas em diferentes lugares (por exemplo, /bin/avk versus /usr/bin/avk); ‘* Em sistemas antigos, que no possuem interpretacio de #! no kernel, alguns shells fazem isso sozinhos, podendo ser criteriosos demais quanto A presenga ou auséncia de espagos em branco entre #1 € 0 nome do interpretador. A Tabela 2-1 lista 0s diferentes limites de tamanho para a linha de #: em diferentes sistemas Unix (esses limites foram descobertos através de experimentagao). Os resultados so surpre~ endentes, uma vez. que com freqiiéncia eles nao slo poténcias de base dois. Tabela 2-1 Limite de tamanko das linhas de #! em diferentes sistemas ‘naforma do sibidr esbo do 80 Temerho mésino ‘plow hac oc erin 7.2 (Ma 05 103.2) siz (arp D4C Aha 5/140 Jom (comp /OEC/NP As 054/15. 1000 HU inst Red 6 7,8, 9 Fda 1 i He PAIS ne eax 10, 11 ww tans /6000 aKa 055 ine x86 FrelSD44 a Ine 86 FrelSD49,5.,5.1 18 Ine 86 NerB601.6 83 Ine 86 Cpent50 3.2 6 solMtrs mrs 28 Sin SPAR 385 Sel 7, 8,9, 10 lone a sos O padraio POSIX mantém 0 comportamento de #1 “no especificado”. Essa € a forma jé padronizada de dizer que uma funcionalidade deve ser usada como uma extensao enquanto estiver de acordo com POSIX. $ cat mus Mestra 0 conteido fi! /bin/eh - inka mégica #! eho | we -1 Comendosa exeeutar CAPITULO 2 * Comesando 35 2.5 A simples opgio ~ diz. que no ha mais opgdes para o shell; trata-se de uma funcionalidade de seguranga para prevenir alguns ataques de spoofing. CONSTRUGOES BASICAS DO SHELL Nesia segiio apresentamos os blocos de construgio bésicos usados em praticamente todos os shell scripts. Sem divida, alguns deles, se nfo todos, serio familiares para vocé devido a0 uso interativo do shell. 2.5.1 Comandos e argumentos A tarefa mais bdsica do shell é simplesmente executar comandos, o que fica mais ébvio quan- do 0 shell é usado interativamente. Vocé digita comandos, um por vez, e o shell os executa: $ ed work; 1s -1 whizprog.c srw-r--r-+ 1 tolstoy devel 30252 Jul § 22:52 whizprog.c $ make Esses exemplos mostram o bésico da linha de comando do Unix. Primeiro, o formato é sim- ples, com espacos em branco (c/ou caracteres de tabulagio) separando os diferentes compo- rnentes envolvidos no comando. Segundo, 0 nome do comando, logicamente, € o primeiro item na linha. Normalmente, as opgdes vém depois dele, ¢ entao quaisquer argumentos adicionais ao comando aparecem apés as opgdes. Nenhuma sintaxe desnecessdria ¢ envolvida, como por exemplo: CCOMMAND=CD, ARG=WORK COMMAND=LISTFILES, MODB=LONG, ARG=WHIZEROG..C Tas linguagens de comando eram comuns em sistemas maiores disponiveis quando o Unix foi projetado. A sintaxe livre do shell do Unix foi uma grande inovacdo na sua época, contri- buindo notavelmente para a legibilidade dos shell scripts. Terceiro, opdes comecam com um trago (ou sinal de menos) e consistem de uma vnica letra Elas so opcionais e podem exigir um argumento (como cc -o whiaprog whizprog.c). Opgdes que nao requcrem um argumento podem scr agrupadas, ¢.g..18 -1t whizprog.c emvezde1s -1 -t whizprog.c (que funciona, porém exige mais digitagio). Opgdes longas sio cada vez mais comuns, particularmente nas variantes GNU dos utilitérios padrao, assim como em programas escritos para o X Window System (X11). Por exemplo: § ed whizprog-2.1 § patch --verbos backup -pl < /tmp/whizprog-1.1-1.2-pateh Dependendo do programa, opgdes longas podem comegar com um ou dois tragos (como mos- trado acima). < /tmp/whizprog-1.1-1.2-patch 6 um redirecionamento de E/S. Ble faz com que patch leia do arquivo /twp /waizprog-1.1-1.2-patch em vez de ler do teclado. Redire- cionamento de E/S é um dos t6picos fundamentais abordados mais adiante no capitulo. Convencionou-se que devem ser usados dois tragos (--) para significar o fim de opcoes. Quaisquer outros argumentos na linha de comando que se paregam com opgdes devem ser tratados como argumentos (por exemplo, tratados como nomes de arquivos). Essa convensdo foi orignalmente apresentada no System V, mas formalizada POSIX. 36 Classic Shell Scripting Finalmente, ponto-e-virgulas separam miiltiplos comandos na mesma linha. O shell os exe- cuta seqiiencialmente, Se voc usar um ‘“e-comercial” (&) em vez de um ponto-e-virgula, 0 shell executa 0 comando em segundo plano (background), 0 que significa que ele no espera pelo término de comando para seguir para executar © préximo comando, O shell reconhece trés tipos fundamentais de comandos: comandos embutidos, fungdes do shell ¢ comandos externos. ‘+ Comandos embutidos sao isto mesmo: comandos que o préprio shell executa, Alguns comandos sio embutidos por necessidade, como cé para trocar de diretério ou read para armazenar em uma variavel do shell entradas obtidas de um usuério (ou de um arquivo). Outros comandos normalmente sio embutidos no shell por questies de e- ficiéncia, Eles tipicamente incluem o comando test (descrito mais adiante, na seco 6.2.4), bastante usado em programagio com shell scripts, e comandos de EJS como echo ou printt. ‘+ FungGes do shell sio trechos de e6digo autocontidos. escritos com a linguagem do shell, ¢ invocados da mesma forma que um comando. A discussdo sobre as fungSes seré feita na Segiio 6.5. Neste ponto, é suficiente saber que cles so invocados, ¢ se comportam, tal qual um comando normal. ‘+ Comandos externos so aqueles que 0 shell executa através da criagio de um proceso separado. Os passos bésicos so: 1. Cria. um novo processo, iniciado como uma c6pia do shel 2. No novo proceso, procura pelo dado comando nos diret6rios listados na varidivel PATH. Join: /usr/bin: fusx/X11R6/bin: jusr/local /bin pode ser um valor comum de EATH (a pesquisa de caminhos € ni € executada quando o nome do comando contém o caractere barra, /). 3. Executa, no novo processo, o programa encontrado através da substituigao do programa shell em execugio pelo novo programa, 4, Quando o programa ¢ finalizado, 0 shell original continua ou a ler o préximo comando do terminal, ou a executar préximo comando do script, Veja a Figura 2-1. (==) SS igura 2-1. Execucbo de um programe Esse € 0 proceso basico. E claro que o shell pode fazer muitas outras coisas como expansio de varidveis e caracteres coringa, substituigéo de comandos ¢ de aritmética, assim por dian- te. Falaremos sobre esses tdpicos & medida que avangarmos no contetido do livro. 2.5.2, Varidveis Uma varidvel & um nome que voc® dé a uma porgio de informagio especifica, como #irse_ nane ou driver_1ic_no. Todas as linguagens de programaco possuem varidveis eo siteil CAPITULO 2 * Comesando 37 niio € uma excegio, Cada variével possui um valor, que € 0 contetido ou informacio que voce atribuiu a cla. No caso do shell, valores de variéveis podem ser, ¢ freqtientemente so, vazios ou seja, no contém caracteres, 0 que ¢ legitimo, comum c itil. Valores varios sao referen- ciados como null ¢ usaremos este termo muitas vezes no resto do livro, Nomes de variaveis do shell comegam por uma letra ou sublinhado e podem conter qualquer nimero de letras, digitos ou sublinhados, ou seja, nao hé limite para 0 ntimero de caracteres em um nome de varidvel. Varidveis do shell contém valores string e também ndo hé limite para o némero de caracteres que eles podem conter (o shel! Bourne foi um dos poucos progr: ‘mas Unix antigos a seguir um principio de projeto “sem limites arbitrétios”). Por exempl $ myvarsthis is a long string that_does_not_mean much Atribui um valor $ echo Smyvar Inprine 0 valor this ie a long string that doos_not_nean_much Como vocé pode ver, a atribuigao de valores a varidveis € feita escrevendo-se o nome da va~ ridvel seguido imediatamente por um caractere = e o novo valor, sem nenhum espago entre eles. Valores de varidveis no shell so extrafdos prefixando-se © nome da variével por um caractere $, Use aspas quando atribuir um valor Titeral que contenha espagos: firsteisaac middle-bashevis last-singer Arribuipdes mihiplas sao permitidas om wna mesma linha fullname="isaac bashevis singer" Protea com aspas os esparos em branco em wnvalor oldnane=$ful inane ‘As spas néo séo necessirias para perservar 08 ‘spaces emum valor Conforme mostrado no exemplo anterior, aspas (assunto discutido mais adiante, na Segio 7.7) nio so necessérias em torno do valor da variével usada como 0 novo valor de uma se- gunda varidvel. Usé-las, entretanto, também néo faz mal ¢ faz-se preciso quando as varidveis sto concatenadas: fullname="$first $middle $last" Aspas necessérias aut 2.5.3 Sai Acabamos de ver 0 comando echo para imprimir 0 valor de myvar ¢ vocé provavelmente lusoU-o na linha de comando. A fungao de echo ¢ produzir safda, tanto para formular pergun- tas, como para gerar dados para posterior processamento. simples com echo 0 comando echo original simplesmente imprimia seus argumentos de volta & safda padrio, cada um separado do outro por um espaco simples, sendo a seqiléncia toda terminada por uma nova linha: § echo Wow is the time for all good men Now is the tine for all good men § echo to come to the aid of their country. to come to the aid of their countzy. Infelizmente, diferentes verses de echo foram desenvolvidas. A verso BSD aceitava um primeiro argumento -n, que faria 0 echo omitira incluso de uma nova linha ao final da string impressa. Por exemplo (0 “sublinhado” representa o cursor do terminal) $ echo -n "Suter your name: * Inprineo prompt Enter your name: _ Digite os dados 38 _ Classic Shell Scripting echo Uso echo [ string... ] Propésito Produzir safda de shell scripts. Principais opebes Nenhuma, Comportamento echo imprime cada argumento na safda pad, separados por um espaco sim- ples e terminados por uma nova linha. Ele interpreta seqiiéncias de escape em cada string que representa caracteres especiais ¢ também controla seu comportamento. Detalhes Diferengas hist6ricas de comportamento entre variantes do Unix tornam di- ficil 0 uso de echo de forma portével em todas elas, a menos que as safdas sejam bastante simples. Muitas verses suportam uma oped ~a. Quando a opedio é usada, echo omite @ nova linha final de sua safda, o que € stil para imprimir prompts (pergun- tas). No entanto, a versio de echo do atual padrio POSIX nao inclui essa opgiio. Veja a discuss no texto. A versio System V interpretava seqliéncias de escape especiais (explicadas de forma resumi- da) dentro dos argumentos. Por exemplo, \e indicava que o echo no deveria imprimir a nova linha final. § echo "Enter your mane": \c* Imprine 0 prompt Enter your nane:_ Digite os dados Seqiiéncias de escape so uma forma de representar em programas caracteres dificeis de ver ou de digitar. Quando echo vé uma seqiiéncia de escape, cle imprime 0 caractere correspon- dente. As seqiiéncias de escape vlidas sio listadas na Tabela 2-2. Tabela 2-2. Segiténcias de escape de echo Seqiénco Descricée \a Coc do oer, grcmente o crater ASCH BEL, \b Backspace rite oro iho fil sate. Nem dso, quasqr carats denes ros xgentseqswer * ds argent sis ioe (ne imps. ME Founfeed \n Nor tan wr Rotor de camo (coninge worn). . igo bier \v ibs veil uN Irie o oc rar \oaaa Cot ress pa ub tl 103 digs CAPITULO 2 © Comegando 39 Em shell scripts a seqiiéncia \e € mais Gtil para chamar a atengio do usuario. A seqiiéncia \ oda ¢ titi! para a manipulagao de terminal (muito) primitivo através do envio de seqiiéncias de escape ao préprio terminal, porém isso nao ¢ recomendavel Como muitos sistemas ainda apresentam como padrao 0 comportamento BSD para 0 echo, Uusamos apenas sua forma mais simples ao longo deste livro. Para safdas mais complicadas. uusamos 0 print, 2.5.4 Saida melhor acabada com printf As diferengas entre as duas verses de echo levaram a uma das mais famosas dores de cabeca relacionadas a portabilidade de variantes do Unix. Durante a primeira rodada de padroniza- cio de POSIX, os membros do comité nao conseguiam concordar sobre como padronizar 0 uso do echo, entdo chegaram a um consenso. Embora o echo fosse parte do padrio POSIX, 0 padro no especificava se o primeiro argumento deveria ser -n ou qualquer outro ar- gumnento que contivesse seqlléncias de escape. © comportamento foi, entZo, deixado como definido pela implementago, o que significa que cada distribuidor deveria documentar 0 que sua versio de echo fazia.* Na verdade, echo poderia ser usado de forma portével somente quando usado da maneira mais simples. Para resolver essa questio, © comando printt da Nine Edition Research Unix system foi adotado. Esse comando ¢ mais flexivel que echo, mas isso a custo de complexiade adicional. O comando printé € modelado com base na rotina da biblioteca C print (). Ble duplica com fidelidade as ferramentas da funcdo (veja a pégina do manual para prinyf (3) €, se voce jé programou um C, C++, avk, Perl, Python ou Tel, provavelmente ja esté familiarizado com 0 bésico. Claro, existem algumas caracterfsticas espectficas da versio do nfvel do shell. O comando print pode imprimir na saida uma string simples tal como o comando echo: printé "Hello, world\n" A principal diferenga que vocé imadiatamente notaré é que, diferentemente de echo, printf no inclui uma nova linha automaticamente. Isso deve ser especificado com \n. A sintaxe completa do comando print possui duas parte printf string-de-formato [argunentos... AA primeira parte € uma string que descreve a safda desejada; ela € melhor fornecida como uma string constante entre aspas. Essa string & uma mistura de caracteres a serem impressos literalmente e de especificagdes de formato, que so encaixes que descrevem como imprimir cada argumento correspondente. A segunda parte 6 uma lista de argumentos, como uma lista de strings ou de valores variaveis, que correspondem as especificacSes de formato, (se ha mais argumentos do que especifica- ges de formato, print percorre as especificagdes de formato na string de formato, reusan- do-as em ordem, até que se conclua 0 processo). Uma especificagao de formato é precedida por um sinal de porcentagem (4) ¢ um especificador de formato. Os caracteres utilizados como especificadores de formato estio discutidos mais adiante no livro. Dois dos prineipais especificadores de formato so 4s para strings © 4d para inteiros decimais * Curiosamente, a versio atual do padtéo apresenta echo como sendo esseacialmente © mesmo da versio do System V, qual processa sequéncias de escape em seus argumentose nfo trata ~n de forma especial, 40 Classic Shell Scripting Dentro da string de formato, caracteres comuns sio impressos literalmente, Seqiiéncias de escape, semelhantes is de echo, sdo interpretadas e entio enviades & saida como 0s caracte- res comespondentes. Especificadores de formato, os quais comegam com o caractere % e ter minam com o caractere de um conjunto definido de letras, controlam a safda dos argumentos conrespondentes vém a seguir. Por exemplo, $s € usado para strings: § printf ‘The first program alvays prints '%s, 48! '\n* Hello world The first program always prints "Hello, world!' Todos 0s detalhes de printf so apresentados na Seco 7.4. 2.5.5 Redirecionamento de E/S basico EJS padrao talvez seja 0 conceito mais fundamental na filosofia de Ferramentas de Soft- ware*. A idéia 6 que programas tenham uma fonte de dados, um dreno de dados (para onde os dados vao) ¢ um lugar para.o registro de problemas. Esses lugares so chamados pelos nomes entrada padrao, saida padrdo ¢ erro padriio, respectivamente. Um programa nio sabe nem se importa com 0 tipo de dispositivo que existe por tr de sua entrada e safdas: arquivos de disco, terminais, drives de fita, conexdes de rede ou mesmo outro programa em execugio! Ao iniciar, um programa pode esperar que esses lugares estejam disponiveis e prontos para serem usados. Muitos, se niio todos, programas Unix seguem este projeto. Por default, eles léem a entrada padrao, escrevem na saida padrao ¢ enviam mensagens de erro para erro padréo. Tis pro- gramas 40 chamados de filtros, por razSes que se tornardo claras em breve. Quando nao especificado de outra forma, entrada padrifo, safda padrio e erro padrio sZo o terminal, o que pode ser visto com cat: $ cat ‘Sem argumentos, é entrada pari, escreve saida podrio now is the tine Digiado pelo useirio nov is the tine Escrito de vlta por cat for all good men for all good nen to come to the aid of their country to come to the aid of their country ” (CiieD, Fim de arquivo Voce pode estar pensando: quem inicializa a entrada, a safda e erro padrio para um pro- grama em execugdo? Afinal, alguém tem que abrir esses arquivos para todos os programas mesmo para 0 shell interativo que o usudrio emprega no momento do Login! A resposta 6 que quando vocé faz 0 login, o Unix estabelece, automaticamente, que 0 lu- gar para a entrada, a safda e o erro padrao € o seu terminal. Redirecionamento de E/S é 0 processo através do qual vocé, interativamente no terminal, ou a partir de um shell script, toca os Iugares de onde a entrada vem ou para onde a safda vai. * “EIS padrdo”, como useda aqui, no deve ser confundide com a biblioteca UO da biblioteca padido de C, cuja interface & efinidaem “seaio.ns, embora a fungdo dela seja fomnecer esse abstragdo para programas em C. CAPITULO 2 * Comesando 41 2.5.5.1 Redirecionamento e pipelines O shell fornece varias notagdes sintiticas para especificar como trocar as fontes e destinos de E/S padrdes do sistema. Aqui abordaremos as notagdes bésicas; mais adiante, trataremos, do contetido completo. Seguindo das mais simples 4s mais complexas, as notagSes so as seguintes: Troque a entrada padrito com < Use programa < arquivo para fazer com que a entrada padrio do programa seja arquivo: tr -€ '\r! ¢ dos-file.txt. Troque a saida padrao com > Use programa > arquivo para fazer com que a saida padrio do programa seja arquivo: tr -d '\r! ¢ dos-file.txt > unix-file.txt Essa invocagio de tr remove os caracteres ASCII carriage-return de cos-file.txt, CO- Iocando os dados transformados em unix-file. txt. Os dados originais em dos-file.txt no so alterados. (O comando tx € discutido com mais detalhes no Capftulo 5.) O redirecionador > cria 0 arquivo de destino caso ele nfo exista. Entretanto, se 0 arquivo existe, ele fica truncado; todo 0 contetido j4 existente € perdido, Adicione ao final de um arquivo com >> Use programa >> arquivo para enviar a safda padrio do prograna para o fim de arquivo. Assim como >, 0 operador >> cria o arquivo de destino se ele nao existir. No entanto, seo arquivo de destino jé existe, em vez de truncé-lo, 0 operador >> adiciona todos 08 novos dados gerados pelo programa em execugio 20 final do arquivo: for £ in dos-filet.txt d '\rt < $f >> big-unix-file.txt (O laco for 6 descrito na Segio 6.4.) Crie pipelines com | Use programa | prograna? para fazer com que a safda padrio de progranal se tome a entrada padrio de prograna2. Embora < ¢ > conectem entrada e safda de arquivos, um pipeline conecta dois progra- mas em execugao. A safda padrdo do primeiro programa tomna-se a entrada padrio do segundo. Em casos favoréveis, pipelines podem ser até dez. vezes mais répidos do que um cédigo similar usando arquivos temporérios. A maior parte deste livro € sobre aprender como juntar as virias ferramentas em pipelines de complexidade e poder crescentes. Por exemplo: tr -d "\r' ¢ dos-iile.tat | sort > unix-file.txt Esse pipeline remove os caracteres carriage-return do arquivo de entrada ¢ ordena os dados, enviando a safda resultante para 0 arquivo de destino. Visualizar dados como 4gua em canos ajuda a entender os pipelines quando se trabalha com ferramentas Unix, Agua nfo tratada vai para um repositério de tratamento e passa por uma série de filtros até que a safda final seja 4gua propria para o consumo humano. 42 _ Classic Shell Scripting De forma semelhante, em scripts, voc’ freqilentemente tem dados brutos em algum formato de entrada definido ¢ precisa de dados processados como saida (processar pode significar muitas coisas: ordenar, somar ¢ computar médias, formatar para impressio etc.). Voce co- mega com os dados originais entio constréi um pipeline, passo a passo, de forma que cada estagio do pipeline refina mais e maisos dados. Se voe8 é novo no Unix, olhar para como “‘funis” de dados — dados entram pelo lado ‘mais amplo e saem pelo lado mais estreito — pode ajudar. © Uso tr [opeées] Lista-de-caracteres-fonte lista-de-caracteres-reposi- so Propésito Traduzir caracteres, Por exemplo, conversio de caracteres maitisculos para minéisculos. Opges permitem remover caracteres e aglutinar a ocorréncia de caracteres idénticos. Principais opgoes Complementa os valores em 1ista-de-caracterea-fonte. Os carac- teres que tx traduz tornam-se aqueles que nao esto em 1ista-de- caracteres-fonte, Essa opgdo é normalmente usada com -a ou -s. Igual a -c, mas opera em caracteres (possivelmente multibyte), no valores de byte binatios. Veja Detalhes, ‘Remove caracteres em 1ieta-de-caracteres-fonte da entrada em vez de traduzi-los, Agrupa, eliminando, caracteres duplicados. Cada seqiiéncia de carac- teres repetidos listados em lista-de-caracteres-fonte é substituida por uma tinica instncia do caractere. Comportamento Age como um filtro, tendo caracteres da entrada padao ¢ escrevendo-os na safda padrio, Cada caractere de entrada em Iista-de-caracteres-fon- te substitufdo pelo caractere comespondente em Lista-de-caracteres- repos igo. Caracteres 20 estilo POSIX e classes de equivaléncia podem. ser usados e 1 também suporta uma notago para caracteres repetidos em Lista-de-caracteres-fonte. Veja as paginas do manual para tr(1) paraos detalhes de operagdo no seu sistema. Detalhes De acordo com POSIX, a opgo -c opera sobre valores de byte binério enquanto -c opera sobre caracteres da forma como especificados pelo lo- cale corrente. Até meados de 2005, muitos sistemas ainda no suportavam a opgiio -c. CAPITULO 2 * Comesando 43 5 Umma tia dica: ao construir pipelines, tente eoorevé-los de forma que a quan- tidade de dados sejareduzida a cada estégio. Em outras palavras, se voce tem dois passos que podem ser executados em qualquer ordem, coloque aquele que reduzira a quantidade de dados primeiro. Isto melhora a eficiéncia geral de scu script, pois © Unix ter que mover menos dados entre programas e, assim, cada programa teri menos trabalho para fazer Por exemplo, use grep para escolher linhas de inteesse antes de wsar sort para ordené-ls; assim sore terd menos trabalho. 2.5.5.2 Arquivos especiais: /dev/null e /dev/tty Sistemas Unix fornecem dois arquivos especiais que so particularmente titeis em progra- magio shell. O primeiro arquivo, /dev/null, € conhecido como “balde de dados”. Dados enviados para ele so descartados pelo sistema. Em outras palavras, um programa que escreva dados neste arquivo sempre acredita que escreveu os dados com sucesso mas, na pritica, nada 6 feito. Isso ¢ stil quando vocé precisa do cédigo de saida de um comando (descrito na Seto 6.2) mas nio de sua saida. Para testar se um arquivo contém um padriio, pode-se fazer como ‘no exemplo: if grep pattern myfile > /dev/null then . Padrio encontrado else Pact ndo encontrado i Em contraste com escritas, leituras de /dev/nul1 sempre retornam “fim de arquivo” ime- diatamente. Em programacio shell, é raro haver leitura a partir de /dev/mul1 € raro, mas é importante saber como o arquivo se comporta. 0 outro arquivo especial é /dev/tty. Quando um programa abre esse arquivo, o Unix auto- ‘maticamente o redireciona para o terminal real (console fisico ou porta serial, ou pseudoter- minal para redes e Logins gréficos), associado ao programa. Isso é particularmente itil para aleitura de entradas que tm que vir de um humano, como senhas. Também é ttil para gerar mensagens de erro: printé "Enter new password: * Solita entrada stty -echo Dasligao echo de caracieres digtades read pass < /dev/' Teserta printf "Enter again: * Solctarovamente read pass? < /dev/sty Lnovamente, par verifcasdo stty ecko Nao equega de igar novamente 0 echo O comando stty controla varias configuragdes de seu terminal (ou janela)*. A opgdo -echo desliga a impressio automética de todos os caracteres que vocé digita; stty echo a restaura. 2.5.6 Procura de comandos basica Anteriormente, mencionamos que o shell procura por comandos ao longo do caminho de procura, $ear#. Trata-se de uma lista de diret6rios separados por dois pontos em que se * sstty é possivelmente 0 comando Unix mais barroco e complicado que existe. Veja a pina de manual de sty(1) para os etalhes mais sérdidos, ou Unix in a Nushet 44 __ Classic Shell Scripting encontram comandos. Comandos podem ser executéveis compilados ou shell scripts; da pers- pectiva do usuério, nfo hé uma distingdo real entre eles. © caminho padrio varia de sistema para sistema. Ele conterd pelo menos /bin e /usr/ bin, Pode conter /usx/%11R¢ /bin para programas X Windows e pode também conter / usx/Locall /bin para programas que seu administrador local de sistema tenha instalado. Por exemplo: § echo ¢PATH /bin: /usr/bin: /usr/XL1R6/bin: /uer/Local /bin 0 termo “bin” para diret6rios que contém executéveis é uma abreviagao para binério. Voce também pode imaginé-lo como tendo o significado correspondente em inglés — um lugar que contém coisas; nesse caso, programas executéveis. Quando voos escreve seus prOprios scripts, & interessante ter seu proprio bin para colocé-los e fazer com que 0 shell encontre-os automaticamente. Isso ¢ ficil de fazer. Apenas crie seu pr6prio diretério bin ¢ adicione-o a lista em $PATH: $ca Wi para odietSrio home § mkdir bin (Coie um divetério ba pessoal § my nusers bin Cologue nosso script § PATHs§PATH:$HOME/bin ‘Adicione nosso diretério bin a PATHE § musers Tose 5 Ossello encontra Para tornar a mudanga permanente, adicione seu diretério bin a spaT# no seu arquivo .pro- file, que é lido sempre que vooé faz login, colocando uma linha como a seguinte ao final dele: PATH=PATH: SHOME/bin Componentes vazios em rat significam “o diret6rio corrente”. Um componente vazio pode ser designado por dois “dois pontos” sucessivos no meio do valor do caminho, ou por uum “dois pontos” no infeio ou no final, o que coloca o diret6rio corrente em primeiro ou por «timo, respectivamente, no caminho de procura. PATH=: /bin: /usr/bin: /usx/X11R6/bin: /usr/locai/bin _Diretiriocorrente no info PATH=/bin: /usr/bin: /usr/X11R5/bin: /usr/Local/bin: —_Diretéri corrente por itino PATH=/bin: /usr/bin: /ust/X116/bin: :/usr/locai/bin _Diretériocorrent no meio Se voeé quiser incluir o diret6rio corrente no caminho de procura, use preferencialmente um. Ponto em $PATH; isso faz com que 0 que est acontecendo fique mais claro para o leitor de seu programa, Em nossos testes, encontramos duas verses do mesmo sistema que néo suportaram correta- mente o uso de um componente vazio ao final de $2\TH . Assim, componentes vazios repre- sentam um problema menor de portabilidade. Te Em geral, voc! nfo tom o direticio coments no seu caminho ¢ isso representa Sg. umproblema de segurange (veja 0 Capitulo 15 para mais informegbes). Desere- LS 42 vemos componentes vazios somente para que voc® entenda como a procura de ccaminhos funciona. 26 CAPITULO 2 * Comesando 45 ACESSANDO ARGUMENTOS DE SHELL SCRIPTS Os chamados pardmetros posicionais representam argumentos de linha de comando dos sitel! scripts. Também representam argumentos de fungdes do shell. Argumentos individuais so nomeados por niimeros inteiros. Por razdes hist6ricas, voc precisa colocar 0 ntimero entre chaves se ele for maior do que nove: echo first arg is $1 echo tenth arg is ${10} ““Varidveis” especiais fornecem acesso a0 mimero total de argumentos que foram passados € para todos os argumentos de uma vez.s6, Mostraremos detalhes mais adiante, na seco 6.1.2.2. Suponha que voc€ queira saber qual terminal um determinado usuétio esté usando. Mais uma vez vocé poderia simplesmente usar 0 comando who € manualmente vasculhar a saida 0 que, na verdade, € dificil e suscetivel a erros, principalmente em sistemas com vérios usuarios. Dessa ver.o que vocé quer fazer € procurar por um determinado usufrio na safda do comando who. Bem, procurar por algo é um trabalho para o comando grep, pois ele imprime linhas que casam com padrio dado em seu primeiro argumento, Imagine que vocé est4 procurando pela usudria betsy porque voce realmente precisa transmitir uma mensagem a ela: § who | grep betey Onde esd beisy? betsy ——pto/3 Dec 27 12:07 (flago-r-us.exanple.con) Agora que sabemos como encontrar um determinado usuério, podemos juntar os comandos em. tum script sendo 0 seu primeiro argumento sendo 0 nome de usuério que queremos encontrar: § cat > finduser Cria arquivo novo #1 Poin/ad # finduser --- verisic Ligado a0 sistena © usuario chanado pelo primeiro argunento esté who | grep $1 “D Fim-de-arquivo $ chmod +x finduser Torntlo execuével $./Anduser betsy Testo: procurarbesy betsy pts/3 Dec 27 11:07 (flags-r-us.example.con) §./Anduser benjanin Agora procrar pelo bom e velo Ben benjamin dtlocal Dec 27 1:55 (kites.exanple.con) § my Sinduser SEOME/bin Salvi: to em nosso divetério bin pessoal A linha que comega com # finduser--- €um comentério. O shell ignora tudo de # até o fim da linha (de forma coincidente; a linha especial com #!, descrita anteriormente, age como um. comentério quando o shell Ié um script) . Comentar o seu cédigo é sempre uma boa idéia. Isso ajudard alguém, ou voc® mesmo daqui hé um ano, a descobrir 0 que voc® estava fazendo e por- qué. Depois de ver que o programa funciona, 0 movernos para 0 nosso diret6rio bin pessoal Esse programa no é perfeito. O que acontece se niio passarmos nenhum argumento? § finduser Usage: grep [OPTION]... PATTERN [PILE]. Tey 'gxep --help! for nore information. Veremos na segio 6.2.4 como testar o ntimero de argumentos de linha de comando ¢ tomar a acdo apropriada quando o ndmero de argumentos correto nao € fomecido. 46 _ Classic Shell Scripting 27 28 RASTREAMENTO DE EXECUCAO SIMPLES. Como o desenvolvimento de programas é uma atividade humana, haverd vezes em que seu script simplesmente néo faréi o que vocé quiser que ele faga. Uma forma de ter uma idéia do que seu script esté fazendo € ativar o rastramento de execugio (execution tracing). Isso faz. com que o shell imprima cada comando & medida em que eles so executados, precedidos por “4” — ou seja, um sinal de mais seguido de um espago (vocé pode modificar 0 que € impres- so atribuindo um novo valor & varivel PS4 do shell). Por exemplo: $ sh -x nusers Execitar com rasireamento ligado + who Rastreamento de comandos +we -1 7 Saidaatwal Voce pode ativar 0 rastreamento de execugdo de um script usando set -x € desativé-lo nova- mente com set +x. Isso é mais titil em scripts complexos. A seguir, um programa simples para demonstrat 0 funcionamento: § cat > tracel.sh Criaseript fi! /bin/en ed Ligao rastreamenio echo Ist echo Facalguma coisa Derliga 0 asireamento Fazalguma outa coisa Encerra com fn-de-arquivo § chmod 4x tracel.sh ‘Torna o programa exeeutivel §./tracel.sh Executé-o 4 echo 1st ecko Primeira linha rastreada Ast. echo Said do comands + set tx Prixima linha rastreda ‘2nd echo Seida do préximo comando Quando executado, set -x nio € rastreado, pois o rastreamento no € ativado até que a exe- cugio do comando se complete. Da mesma forma, set +x € rastreado, pois 0 rastreamento também nao é desativado até que 0 comando se complete. O echo final no é rastreado, pois 0 rastreamento estd desativado naquele ponto. INTERNACIONALIZAGAO E LOCALIZACAO. Escrever software para um pablico internacional € um problema desafiador. A tarefa € geral- mente dividida em duas partes: internacionalizagdo (i18n € a abreviagio de internationaliza- tion, pois a palavra tem 18 letras entre a primeira e a dltima) e localizagdo (de forma andloga, 110n é a abreviatura de localization). Internacionalizagao € 0 processo de projetar software de forma que ele possa ser adaptado para comunidades de usuérios especificas sem que seja necessério mudar ou recompilar 0 ¢6- digo. No minimo, isto significa que todas as strings de caracteres deve ser acessadas através de chamadas de biblioteca que tratam de pesquisa de tradugées adequadas em catélogos de mensagens. Tipicamente, as tradugdes so especificadas em arquivos de texto comuns que acompanham o software ¢ so enti compiladas por gencat: ou nsgfat para arquivos binérios compactos a fim de agilizar a pesquisa. Os catélogos de mensagens compiladas so entio insialados em um diret6rio do sistema na érvore de diret6tios, como nos convencionados pelo CAPITULO 2 © Comegando 47 projeto GNU /usr/share/locale e /usr/local/share/locale ou, em sistemas Unix comer Ciais, /usr/1ib/n1s ou /usr/1ib/ locale. Mais detalhes podem ser encontrados nas pdginas do manual de setlocale(3), catgets(3C) ¢ gettext(3C), Localizagio € 0 processo de adaptagzo de software internacionalizado para uso de comuni- dades de usudrios especificas. Isso pode exigir a tradugdo da documentagéo de software ¢ todas as safdas de texto produzidas pelo software e, possivelmente, a modificagio, na saida do programa, do formato do sistema monetério, das datas, dos niimeros, dos hordrios, das tunidades de medida, e assim por diante. O conjunto de caracteres usado para textos também pode precisar ser trocado, a menos que 0 conjunto de caracteres universal Unicode possa ser usado, ¢ diferentes fontes podem ser requeridas. Para algumas linguas, a dire¢ao de escrita também terd de ser trocada, No mundo Unix, padrdes ISO para linguagens de programacao e POSIX jé apresentam su- porte (limitado, € verdade) para abordar esses problemas, mas muito ainda falta ser feito, e 0 progresso varia substancialmente entre os varios sabores de Unix. Para 0 usuério, a funcio- nalidade que controla qual lingua ou ambiente cultural é afetado € chamada de locale, ¢ € ajustada por uma ou mais varidveis de ambiente mostradas na tabela 2-3. Tabela 2-3. Varidveis de ambiente para locales Wome Desgio as Yeorttzo pre dq vt ic_socr, pra quel fn vr rb, wean Yolo qu scbeseve dass ote rec sce te couare Name oboe gre agape ue eres Name dolor fis de xeric, es, pou esi dnt) 1c MESSAGES Hae dole pr spss errs eres pv menses; oper POSH 1 wowsTaRY Nar dole yr oman deste eee 1c mesa Name dole gr foretagte d mens ve stKe Nome dole yr omen d dts ores Em geral, vocé ajusta ic_aLt para forgar um vnico locale ¢ LANG para fornecer um locale a ser usado quando outros forem. Na maioria dos casos, vocé deve evitar ajustar qualquer outra varivel 1c so. Por exemplo, embora parega mais preciso ajustar £¢_COLLATS quando vocé usa o comando sozt, esta configuragao pode ser conflitante com a configurago de Lc_cT¥2e ou pode ser totalmente ignorada quando 1¢_Atx, est4 configurada. Apenas um tinico nome de locale padrio, ¢, é prescrito pelos padroes ISO C e C++: ele opta pelo comportamento tradicional orientado 2 ASCII. POSIX especifica um nome de locale adicional, POSIX, que é equivalente ac. Exccto os nomes Ce P087x, nomes de locale no so padronizados. Entretanto, a maioria dos distribuidores tem adotado convengGes de nome semelhantes, mas nfo idénticas. O nome de locale codifica uma lingua, um territério e, opcionalmente, um conjunto de eédigos e um mo- dificador. Normalmente, ele € representado por duas letras minésculas do eédigo de Iinguas, 1SO 639, um sublinhado e um cédigo de pafs composto por duas letras maitisculas, de acordo com ISO 3166-1 opcionalmente seguido por um ponto e a codificagiio do conjunto de carae- * Disponivel em hup/iwnies.uoedufpubhethtp/relatediso639.t0. **° Dispontvel em hup:/userpage chee fusberin de/dverseldoc/1SO_3196 hon 48 Classic Shell Scripting teres, uma arroba ¢ a palavra modificadora. Nomes de linguas também so usados. Vocé pode listar todos os nomes de locale reconhecidos em seu sistema da seguinte forma: § loca: lis todas as locales frangais fr BE fr_Beseuro fr BR. isoaaser f2 BE. iso885915¢euro fx BE.utés fr BB.utfseeure Ercan fr_ca.isosass1 fr_ca.utts french Vocé pode descobrir os detalhes de uma determinada varidvel de locale definindo um locale ‘no ambiente (aqui, como um prefixo para o comando) ¢ executando 0 comando Locale com a opcdo -ck uma varidvel L¢_sax. Eis um exemplo de um sistema Sun Solaris que relata informagSes sobre 0 locale de horétio em dinamarqués: $ MC_Aulsda locale -ck LC_TIMs Obrém informagées de locale para tempo dinamarqués 1c TOs fnt=tba 4d tb WY $7 #2" a7" a abday="son"; "nan" "tir" Januar" ;*februar'; "martes" ; "april"; *maj"; "juni" ; "juli september" ; "oktober"; "novenber" ;"decenber" abnon="jan";"feb";"mar*;"apr";"naj";"jun";"jul";"aug";"sep";"okt"; \ "nov"; "deo" erat era_a tnt alt sugust’ ligits="" Ontimero de locales dispontveis varia muito, Uma pesquisa feita com cerca de 20 sabores de Unix nao encontrou nenhum em sistemas BSD e Mac OS X (eles no possuem 0 comando ocate) encontrou apenas cinco em alguns sistemas e quase 500 em verses recentes de GNU/ Linux. O suporte a locales pode ser uma opedo de instalagéo a critério do gerenciador do sistema, assim, mesmo sistemas operacionais de mesma versdio em méquinas semelhantes ‘* MB = megabyte, aproximadamente 1 milhgo de bytes, onde um byte corresponde, convencioaalmeate, a oito bits (Aigitos binf+ios), embora tamanhos maiores e menores de bytes tenham sido usados no passado. Apesar do sistema decimal, no ‘cantesto de computadores, M usualmente significa 2” = 1.048.576. ‘Uma regra prtca é a de que um megabyte equivale aproximadamente & quantidade de texto contida em um livro (300 pési- ‘nas x 60 caracreres/inha = 1,080,000 caractere, CAPITULO 2 © Comegando 49 podem apresentar diferente suporte a Jocale. Encontramos requisitos de sistema de arquivos para suporte a locale préximos de 300MB* em alguns sistemas. Diversos pacotes GNU foram intemacionalizados e 0 suporte a localizago foi adicionado para varios locales. Por exemplo, em um focale italiano, GNU 1s apresenta mensagens de ajuda como: § UC ALL=it 17 1s --help Buscar ajuda GNU ism italiano Uso: 16 [OPZIONE]... (FILE)... Blenca informazioni sui FILE (predetinito: 1a directory corrente) Ordina alfabeticamente le voci se non @ usato uno di -cFtustx oppure --sort. Mandatory argunents to long options are mandatory for short options coo. a, -all non nasconde le voci che iniziano con non elenca le voci inplicite. e.. stampa léutore di ogni file stampa escape ottali per i caratteri non gratict usa blocehi lunghi DINENS byte Note que quando uma tradugdo nao esté disponivel (quinta linha), a lingua original, inglés, é uusada. Nomes de programas e nomes de opges nio sio traduzides porque isso destruiria a portabilidade de software. Atwalmente hé pouco suporte na maioria dos sistemas para o programador shell abordar ques- (Wes de internacionalizagio e localizagio, Entretanto, shel! scripts seguidamente slo afetados por locales sobretudo na ordem de agrupamento e em faixas de caracteres entre expressdes de colchetes em expressdes regulares. Embora descrevamos classes de caracteres, sfmbolos de agrupamento e equivaléncia de classes na Seco 3.2.1, parece bem dificil determinar na documentacéo de Jocales ou ferramentas na maioria dos sistemas Unix quais caracteres so membros dos caracteres e classes de equivaléncia, e quais simbolos de agrupamento esto disponiveis. Iso reflete a imaturidade do suporte a locale em sistemas atuais. Quando o pacote GNU geitext* esta instalado, € possivel usé-lo para dar suporte a interna- cionalizagdo & localizagio de shell scripts. Esse € um t6pico avangado que nao cobriremos, }, mas voce pode encontrar detalhes na Seco Preparando Shell scripts para Inter- igo no manual de geitext As amplas variag6es no suporte a locale e a falta de nomes de locales padronizados, fazem com que seja dificil fazer muita coisa com o emprego de locales em shell scripts, além de forgarem o locale tradicional através da configuragdo de 1.¢_ALL para Cc. Fazemos isso em alguns scripts neste livro quando a dependéncia de locale pode, de alguma forma, produzir resultados inesperados. 2.9 RESUMO A escolha entre linguagens compiladas e linguagens script 6 normalmente feita com base na necessidade da aplicagao. Linguagens script geralmente trabalham em um nivel mais alto do que linguagens compiladas e a perda de desempenho é geralmente compensada pela veloci- dade com que o desenvolvimento pode ser feito ¢ pela habilidade para trabalhar em um nivel mais alto. * Dispontvel em ipfip.gnuore/enufgenexv. 50 _ Classic Shell Scripting O shell é uma das mais importantes ¢ amplamente usadas linguagens script no ambiente Unix. Por ser ubiqua e por conta do padrao POSIX, ¢ possivel escrever programas shell que funcionardo em vérias plataformas de distribuidores. Pelo fato das fungdes do shell trabalha- rem em alto nfvel, programas shell tm elevada taxa de retorno: voce pode fazer muito com relativamente pouco trabalho. A primeira linha #! deve ser usada em todos os shell scripts: esse mecanismo oferece flexibi- lidade, habilitando a escrita de scripts na linguagem ou shell que vocé escolher. O shell € uma linguagem de programagio completa. Até agora cobrimos 0 basico de coman- dos, opcGes, argumentos € varidveis e safda bésica com echo e print. Também vimos ope radores de redirecionamento bésicos, <, >, >> € | com os quais esperamos que voce jé esteja familiarizado. O shell procura por comandos em cada diret6rio de $eaTH. E comum vocé ter um diretério bin pessoal, no qual seus programas ¢ scripts privados so armazenados, e listé-lo em PATH, fazendo uma atribuigdo em seu arquivo.profile. Vimos 0 basico para acessar argumentos de linha de comando e rastreamento de execusaio. simples. Finalmente, discutimos internacionalizacdo ¢ localizaedo, t6picos que esto crescendo em importancia 4 medida que sistemas de computador sio adaptados para as necessidades com- putacionais de pessoas ao redor do mundo. Apesar do suporte para shel! scripts nessa frca ainda ser limitado, programadores shell precisam estar conscientes da influéncia de locales em seus e6digos. 3.1 Pesquisando e Substituindo Conforme discutimos em “Princfpios de Ferramentas de Software” [Seco 1.2), programa- dores Unix preferem trabalhar com linhas de texto. Dados textuais so mais flexiveis do que dados bindrios, ¢ sistemas Unix oferecem uma série de ferramentas que tornam faccis as tarefas de cortar e suprimir trechos do texto. Neste capitulo, veremos duas operagdes fundamentais que aparecem repetidamente em shel! soripts: pesquisa em texto — que procura linhas espectficas de texto — e substituicdo de texto que muda o texto encontrado. Embora vocé consiga fazer muito usando apenas strings constantes de texto simples, ex- pressdes regulares oferecem uma notacao muito mais poderosa para o casamento de varios e diferentes fragmentos de texto usando uma (inica expresso. Este capftulo introduz. os dois “sabores” de expressGes regulares oferecidos pelos varios programas Unix, e ento avanga, abordando as ferramentas mais importantes para a extrac e a manipulagdo de texto, PESQUISANDO TEXTOS O programa mais utilizado (verdadciro “cavalo de batalha”) para encontrar textos (ou “casar textos”, no jargio Unix) € o grep. Em sistemas POSIX, o grep pode usar qualquer um dos dois “sabores” de expressdes regulares, ou casar strings simples. Tradicionalmente, trés programas independentes tém sido usados para pesquisa em arquivos de texto: grep programa original para casamento de textos. Ele usa Expresses Regulares Bésicas (ERBs) conforme definidas pelo padrio POSIX, como descrevemos mais adiante neste capitulo. eorep “grep estendido”. Esse programa usa Expresses Regulares Estendidas (EREs), que & uma notagio de expressdes regulares mais poderosa. A desvatagem das EREs € que elas 52__ Classi Shell Seripting 3.2 podem ser computacionalmente mais caras de usar. No PDP-11 original, que tinha pouco poder computacional, esse era um detalhe importante; em sistemas modernos, porém, faz pouca diferenga. forep “grep Rapido”. Essa variante casa com strings fixas ao invés de expresses regulares usando um algoritmo otimizado para casamento de strings fixas. Além disso, a versio original era a tinica variante que podia casar multiplas strings em paralelo. Em outras palavras, grep € ecrep podiam casar apenas uma tinica expresstio regular, enquanto que © fgrep usava um algoritmo diferente que poderia casar virias strings tentando, de forma eficaz, casar cada linha de entrada com cada uma das strings de pesquisa. O padrdo POSIX de 1992 uniw as tr8s variantes em um sinico programa grep cujo compor tamento é controlado por diferentes opgdes. A verso POSIX casa miltiplos padrées, tanto para ERBs como para EREs. Embora ainda estejam dispontveis, tanto fgrep quanto egrep io hoje marcados como “obsoletos”, o que quer dizer que eles podem ser removidos em pa- drdes subseqtientes. E, de fato, 0 padrio POSIX de 2001 inclui apenas a versio grep, unindo todos os outros comandos. Na pritica, egrep € forep ainda continuam disponfveis tanto em sistemas Unix como em seus equivalentes. 3.1.1. grep simple: O.uso mais simples de grep ¢ feito com strings constantes: $ who Quen estéeutenticado no sistema tolstoy tty Feb 26 10:53 tolstoy pto/a Fob 29 10:59 tolstoy pts/1 Feb 29 10:59 tolstoy pts/2 Feb 29 11:00 tolstoy pts/3 Feb 29 12:00 tolstoy pto/4 Feb 29 11:00 austen pte/S Feb 29 15:39 (nanstie1d-park.exanp1e.com) austen pts/é Feb 29 15:39 (nanstie1d-park example. com) $ who | grep -F austen Onde austen se autentco4? austen pts/S Feb 29 15:39 (nanstield-park.example.com) austen pts/é Feb 29 15:39 (nansfield-park.example.com) Esse exemplo usa a opeiio -P, para pesquisar a string fixa austen. E, realmente, desde que 0 seu padrao nao contenha nenhum caractere de expressao regular, © comportamento padrio do gzep (sem opgGes) ¢ efetivamente o mesmo que usando a opeio -F: $ who | grep austen Sen-F mesno retade austen pte/s Feb 29 15:39 (nansfield-park. example.com) austen pto/é Feb 29 15:39 (nansfield-park. example. com) EXPRESSOES REGULARES Esta segdo oferece uma breve revisio da construgio e do casamento de expressOes regulares. Em particular, ela descreve as construgties ERB e ERE POSIX, que pretendem formalizar os dois “sabores” bésicos de expresses regulares encontrados na maioria dos utilitérios Unix © N, de, Em inglés chama-se de Fast grep. CAPITULO 3 * Pesquisando e Substitvindo 53 grep Uso grep lopedes ...] padrao larquivos Proposito Imprimir linhas de texto que casem com um ou mais padres. Freqlientemen- te, esse ¢ o primeiro estégio de um pipeline que fard um processamento maior dos dados que casaram, Principais Opcoes 3 ‘Casa usando expressOes regulares estendidas, crep -2 substitui 0 co- mando egrep tradicional - Casa usando strings fixas. grep -F substitui o comando farep tradi- ional. ~e pat-List Geralmemte, o primeiro argumento que nao é uma opcio especifica 0 padirdo a ser casado. Miltiplos padres podem ser fornccidos colocan- do-os entre aspas e separando-os em linhas diferentes. Se um padréo iniciar com um sinal de menos, 0 grep pode ficar confuso ¢ o trats-lo ‘como uma opedo. A opgo -e especifica que seus argumentos so um padrao a ser casado, mesmo que eles comecem com um sinal de me- os. -f pat-file Le os padres a partir do arquivo pat-file Ignora 0 caso na pesquisa pelo padrio. a Lista os nomes dos arquivos que casam com o padtio, ao invés de ape- ‘as imprimir as linhas que se casaram. 4 Em vez de imprimir as linhas para a safda padréo, o grep encerra com sucesso se ele casar com o padrao, e sem stucesso caso contrério, (Ain- da niio discutimos 0 sucesso/ndo sucesso; veja “Status de encerramen- 10” (6.2). Suprime as mensagens de erro, Essa opgdo € seguidamente usada em conjunto com -¢. ‘Imprime as linhas que ndo casam com o padrio. Comportamento Lé cada arquivo passado na linha de comando. Quando a linha casa com 0 padrio que esti sendo pesquisado, ele imprime a linha, Quando miltiplos arquivos so passados, 0 grep antecede cada linha com 0 nome do arquivo € um sinal de dois-pontos (*:”). Em caso de omissao serio usadas ERBS. Detalhes ‘Vocé pode usar miltiplos -e e -£ para construir uma lista de padtdes a serem pesquisados. 54 __ Classic Shell Scripting Acreditamos que vocé jé tenha tido contato com expressées regulares ¢ com casamento de padres antes de ler este livro. Nesse caso, essas subsegées resumem como voc pode esperar usar expressées regulares para desenvolvimento de shell scripts portéveis, Se vocé nao teve nenhum contato com expressdes regulares, o material aqui apresentado pode ser um pouco condensado demais, e talvez vocé precise buscar uma fonte mais introdutoria, como 0 livro Learning the Unix Operating System (O'Reilly) ou sed & awk (O'Reilly). Como expresses regulares siio uma parte fundamental dos paradigmas de uso e construgao de fer- ramentas do Unix, qualquer investimento que voc faga para aprender a usé-las, e a usé-las bem, seré amplamente recompensado ao longo do tempo. Mas e se, por outro lado, hé anos voc vem suprimindo, fatiando e partindo textos com. expressGes regulares, talvez. voc® ache nossa abordagem superficial. Se esse & 0 seu caso, recomendamos que vocé revise a primeira parte, que resume as ERBs e EREs POSIX de for- ma tabulada, pule o resto da seed, e parta para uma fonte mais aprofundada, como o livro Mastering Regular Expressions (O'Reilly). 3.2.1 O que é uma expresso regular? Expressdes regulares so uma notagio que permite que vocé pesquise por texto que se encaixe em um critério em particular, assim como “comeca com a letra 2”. A notago permite que vocé escreva uma tinica expresso que pode selecionar, ou casar com, miltiplas strings de dados. Além da notagio tradicional para expresses regulares no Unix, as expresses regulares PO- SIX permitem que vocé: * cscreva expressdes regulares que expressem pedidos de seaiiéncias de caracteres especi- ficos, ou equivalentes, de um determinado locale; ‘© escreva suas expressdes regulares de forma que elas néo dependam do conjunto de carac- teres subjacente do sistema. Um grande nimero de utilitérios Unix tem, de uma forma ou de outra, seu poder derivado de expresses regulares. Uma lista parcial inclui o seguinte: ‘* a familia grep de ferramentas de pesquisa de linhas que casam com padres: grep € egrop, que estilo sempre disponiveis, assim como 0 utilitario nao padrao, porém util, agrep*; + o editor de fuxos (streams) sed, descrito mais adiante neste capftulo, que faz alteragdes no fluxo de entrada; ‘+ linguagens de processamento de strings, tais como awk, Icon, Perl, Python, Ruby, Tel ¢ outras; isualizadores de arquivos (eventualmente chamados de paginadores), assim como 0 nore, page € pg, comuns em sistemas Unix comerciais, e 0 popular paginador less**; * editores de texto, assim como 0 venertivel editor de linhas ed, 0 editor padrio de tela vi, ¢ 0s editores adicionais populares, como enace, jed, jove, vile, vine outros. * A verso original do Unix de 1992 esta cisponivel em fp:/fo.s.arizona edwagreplagrep-?.04.1arZ.. Uma versio atual para 6¢ sistemas Windows encontre-se em hiip./ivwr. teres delagrep/337/agrep337 zip. Diferentemente da maieria dos sofwa res dispontveis para download que citamos neste lio, o agrep mio pode ser usado livemente para qualquer propésito: Veja (06 axquivos de permissées que scompanham 0 programa. ‘Assim chamado para fazer um tocadilho com o nore. Veja fip/fip.gnu.ore/enufess. CAPITULO 3 * Pesquisando e Substitvindo 55 Pelo fato de as expressées regulares serem to centrais para o uso do Unix, vale a pena conhe- c6-las bem, € quanto mais cedo voeé o fizer, melhor serd. Em termos priticos, expresses regulares sto construfdas a partir de dois componentes bsi- cos: caracteres normais e caracteres especiais. Os caracteres especiais estio relacionados na Tabela 3-1, a seguir. Em alguns contextos, mesmo caracteres especiais sao tratados como nor- mais. Os caracteres especiais sao também chamados de metacaracteres, termo que usamnos 20 longo deste capitulo, A tabela 3-1 lista os metacaracteres POSIX ERB ¢ ERE. Tabela 3-1 Metacaracteres POSIX ERB e ERE Gorucers \ Maa} a FETE a F ? ee Be ca ca Re Re RE ‘Siete do poito Gerdnere, design sfc exec do once squire senna, bit um sit spec poe ora seu, amo wm \(...\) €\{. Je (asec egy contr rt, eey nz. Agus ragemes pole desiita camer de contee de noi. (onc ur ier ules (cu rho) do crc quo micadeinettamat. Pa Es, 0 -cnctore precedente pode ser una expresso regalat. Pe exerplo, jd que . (penta) sonia quaker conte, + siti “ts cor unr eng de ues care, Pm 3s,» nfo um const epee ef mein aacte da ecpesi. (as expresso eg stseiete nin da ina ust. EB: consider expecal arene ‘oink de ino, ERE espace am qe pon, (se «exes egder oro find non sig. E28: cond expec sovene o fil dine ER: eye em ele pnt hunado de exes dco case a ucla des coc moi eles cae 1, Ui ie (-) ndcoua ie de crc consti, (Codes so series cc, «prt ni rte). U casero (* come pmo cae inet o sete: ee ase ‘on qolner rar gue nto ese rasta. Un be oun fees (1) come pelo ‘ter tfod coma um mend it. odes esac so tte cee menos N. doT. Bim ingles € chamada de bracket expression. 56 _ Classic Shell Scripting A Tabela 3-2 apresenta alguns exemplos simples. Tabela 3-2 Exemplos simples de casamentos com expressdes regulares reso Gosmenio. toistoy Asst lotesto1stoy, om gud dour nko “tolatoy Assets tolstoy, wit do unalida tolstoys As ete ote to1stoy, no fal dune iho “tolstors Urol cnendo extort seta lens eon st-cy, enn mis (relotstoy Asstlotesto1stoy, outset tol stoy, an qq lga de a rho tol.toy Ass tes to, quer canter, css as coy, em que per dike to. Ass tes to, quer sera de 20 ovis erect, ¢stsleos toy, em ankuer lugar dale (fr sample, ortoy, toletoy, tolMHotoy, ec pr dat) 3.2.1.1 Expresses POSIX com colchetes Com 0 objetivo de contemplar ambientes de Ifngua nfo inglesa, o padro POSIX aprimorou a habilidade de manipular faixas de caracteres (por exemplo, (a-2]) para casar caracteres que nio existem no alfabeto inglés. Por exemplo, o francés ¢ é um caractere alfabético, mas acclasse tipica {a-2] no casaria com ele. Além disso, 0 padriio fomnece sequéncias de carae- teres que sio tratadas como uma tinica unidade quando casadas e quando ordenadasem uma string de dados (por exemplo, existem trés locales em que os dois caracteres ch so tratados, como uma unidade, e devem ser casados e ordenados dessa forma). A crescente popularidade do conjunto de caracteres padrio Unicode adiciona mais complicagbes ao uso de faixas sim- ples, fazendo com que sejam ainda menos apropriadas para as aplicagGes modernas. POSIX também alterou © que antes era c terminologia comum. O que vimos anteriormente como uma expresso de faixa é também freqlentemente chamada de uma “classe de carae- teres” na literatura Unix. Agora, porém, ela € chamada de uma expresso de colchetes no padrio POSIX. Dentro de uma “expresso de colchetes”, além de caracteres comuns, como \2, 1,€ assim por diante, voc também pode ter componentes adicionais. Estes so: Classes de caracteres Uma classe de caracteres POSIX consiste em palavras-chave contidas em (+ © =). As palavras- chave descrevem diferentes classes de caracteres, assim como caracteres alfa- numéricos, caracteres de controle, etc assim por diante. Veja a Tabela 3-3. Simbolo de agrupamento Um stmbolo de agrupamento* é uma seqiiéncia com miiltiplos caracteres que deve ser tratada como uma unidade. Ela consiste em caracteres contidos em [. ¢ .). O agrupa- mento de sfmbolos € espectfico do locale em que ele esté sendo utilizado. Classes de equivaléncia ‘Uma classe de equivaléncia lista um conjunto de caracteres que devem ser considerados equivalentes, assim como ee @. Ela consiste em um elemento nomeado pelo locale, ¢ contidoem [=e =]. Essas trés construgdes dever aparecer dentro de colchetes em uma expressio de colchetes, Por exemplo, [{:aipaa:] !] casa com um caractere qualquer alfabético ou com a exclamagio, © de T.: Nesta tradusio foi aotado otermo agrupamento para otermo em ingles collating, CAPITULO 3» Pesquisando ¢ Substitvindo 57 © {L.ch.1] casa com o elemento de agrupamento ch, mas no casa apenas com a letra ¢ ou com a letra h isoladamente, Em um locale francés, {{ £oo.out Preprocessae remove a inhasvacias “esi caracteres especiais apenas no in{cio e no final, respectivamente, de uma ERB. Em. uma ERB como ab*cé, 0 * significa ele mesmo. Portanto, nesse caso, também em ef gh, 0 § significa ele mesmo. E, como com qualquer outro metacaractere, \* e \g podem ser usados, assim como também pode [$] .* 3.2.2.5 Precedéncia de operadores nas ERB: Assim como nas expresses mateméticas, os operadores tém uma precedéneia definida nas express6es regulares, Isso significa que certos operadores so aplicados antes de (tém maior precedéncia que) outros operadores. A Tabela 3-5 mostra a precedéncia para os operadores das ERBs, dos de maior para os de menor precedéncia, * A expressto comespondente [*] no € uma expressao regular vilida. Cerfique-se de saber o porque. 62_Classie Shell Scripting Tabela 3-5 Precedéncia de operadores ERB, da maior para a menor Operadr Signifcade Ll teal Gl Sinks ences ov agupamens de craes \necavaractere Netcorp a Bigesses ences UA) \aigit ‘thors ferocs ponis “WN Renee do ees re deen crete rederte semsinble Grates ‘s Acres 3.2.3 Expressées regulares estendidas EREs, conforme o nome indica, tém mais funcionalidades que expressdes regulares basicas, Muitos dos metacaracteres e das funcionalidades sao idénticos. Porém, alguns metacaracteres, que parecem similares aos seus pares nas ERBS, tém significados diferentes. 3.2.3.1 Casando com caracteres énicos Quando o assunto ¢ casar caracteres tinicos, as EREs sao essencialmente iguais as ERBs. Em particular, caracteres normais, a barra invertida para proteger os metacaracteres, as expres- 85es em colchetes, tudo se comporta conforme descrito anteriormente para as ERBS. Uma excego notével aparece no awk, no qual a \ tem um significado especial dentro de ex- pressdes de colchetes. Assim, para casar com um abre-colchete, um hffen, um fecha-coichete, ou uma barra invertida, vocé pode usar {\ {\-\]\\]. Novamente, isso reflete uma pratica his- tric 3.2.3.2 Referéncias para tras nao existem Referéncias para tris nao existem nas EREs.* Os parénteses tém um significado especial nas EREs, mas servem para um propésito diferente do que eles desempenham nas ERBS. Em uma ERE, \{¢ \) casam literalmente com os earacteres abre ¢ fecha parénteses. 3.2.3.3 Casando miltiplas expresses regulares com uma expresso As principais diferengas das EREs para as ERBs estio na rea de casamento de méltiplos caracteres. O * nao funciona como nas ERBs.** Express6es intervalares também esto disponiveis nas EREs; porém, elas so escritas usando colchetes diretamente, pois eles nfo precisam ser precedidos por barras invertidas. Assim, rnossos exemplos anteriores de “exatamente cinco ocorréncias de um” ¢ “entre 10 ¢ 42 instin- cias de q” so escritos a{5) e a{10,42}, respectivamente. Use \{ ¢ \} para casarliteralmente com as chaves. O POSIX intencionalmente deixa, em uma ERE, o significado de um abre chaves { scm um fecha chaves } em uma ERE como “indefinido”, * Essa caracterstca refletediferengas no comportamento histérico dos comandos gzep ¢ egrep,¢ nifo uma incapacidade dos ‘casalores de expresso regular. Assim & vida no Uni ** Uma excegéo € que o significado de um * como primeiro caractere de uma ERE € “indefinido”, enquanto que em uma ERB ‘ele significa o literal * CAPITULO 3 * Pesquisando e Substitvindo 63 EREs possuem dois metacaracteres adicionais para um controle mais refinado do casamento, conforme a seguir: ‘Casa zero ou uma vez com a expresso regular precedente ‘Casa uma ou mais vezes ccm a expresso regular precedente \Voeé pode pensar no caractere ? como significando “opcional”, Em outras palavras, 0 casa mento da expresso regular precedente pode, ou no, ocorrer. Por exemplo, ab?e casa com ambos, ac ¢ abc, mas nenhum mais (compare com a expresso abe, que pode casar com qualquer nimero de caracteres b intermediérios) Occaractere + € conceitualmente semelhante ao metacaractere *, exceto pelo fato de que pelo menos uma ocorréncia do casamento da expresso regular precedente deve ocorrer. Assim, bse, casa com abo, abe, abbbo, e assim por diante, mas no casa com ac. Vocé sempre pode substituir uma expresso regular da forma ab+e por uma abbte; porém, o + pode poupar bastante digitagao (e potenciais erros de digitag4o!) quando a expressio regular precedente é complicada, 3.2.3.4 Alternatives Expressbes de colchetes permitem que voe8 facilmente diga “case com este caractere, ou este caractere, ou ..” Porém, elas ndo permitem que vocé especifique “case com esta seqiiéncia, ou esta seqiiéneia, ou ..” Yoc8 pode fazer isso usando o operador de alternativa, que é a barra vertical ou caractere pipe (|). Simplesmente escreva as duas seqténcias de caracteres, sepa- radas por pipe. Por exemplo, read | write casa com ambos, read e write, fast |slew casa com ambos, fast e slow, e assim por diante. Voc® pode usar mais de uma: s1eep|éoze| arean|ncd off |s lumber casa com cinco expresses. O caractere | possui a precedéncia mais baixa de todos os operadores das EREs. Assim, 0 lado esquerdo se expande completamente para a esquerda, até encontrar o | precedente, ou 0 infcio da expressio. De forma parecida, o lado dircito do | se expande para a direita, até encontrar o préximo caractere | ow o fim da expressio regular. As implicagdes diso sao dis- cutidas na préxima seco. 3.2.3.5 Gropos Voce pode ter notado que, para as EREs, nds fulamos que os operadores so aplicados & “ expresso regular precedente”. A razilo & que os parénteses ((...)) fornecem gruposem que 0s operadores podem ser aplicados. Por exemplo, (why) + casa com uma ou mais ocorréncias da palavra way. Grupos sio particularmente valiosos (e necessérios) quando se esté usando alternativas. Eles, permitem que voc construa expresses regulares complicadas € flex(veis. Por exemplo, Tt] he (cPu|computer) is casa com sentengas usando tanto CPU como computer entre o The (ou the) eo is. Note que aqui os parénteses sio metacaracteres, nfo uma entrada de texto a ser asada. Grupos sto freqtientemente necessérios quando se usa 0 operador de repeti¢ao em conjunto com alternativas. zead|writes casa com exatamente uma ocorréncia da palavra read, ou com ‘uma ocorréncia da palavra write, seguida de um nimero qualquer de caracteres e (writee, weiteee, ¢ assim por diante). Um padréo mais itil € (read|write] +, que casa com uma ou mais ocorréncias de qualquer uma das palavras read ou write. 64 Classic Shell Scripting (sonethingl)+ Uma aes patie de someting (sonething2) ([:space:]]* sonethingl 6sonething2 silat soiled esos read| write something? 61a” oie Figura 3.1 Leitura de uma expresstio regular complicads. Claro que (read |yrite) + nilo permite espagos em branco entre as palavras. ((read|white) U{sepace:]]*)+ € uma expresso regular mais complicada, porém mais realista. A primeira vista, ela parece um pouco “opaca”. Porém, se vocé quebrar a expresso em componentes, de fora para dentro, nao ¢ tio dificil entende-ta. Isso ¢ ilustrado na Figura 3-1. O resultado é que essa tnica expresso regular casa com miltiplas e sucessivas ocorréncias de read ou write, possivelmente separados por caracteres de espaco. Ouso de um * depois de ({:space:]] uma questio de decisio, Usando-se um * em vez de lum +, 0 casamento aceita palavras no final de uma linha (ou string); porém, isso abre a possi- bilidade de casamento de palavras sem espagos entre elas. A pritica com expressGes regulares, seguidamente leva a situagoes em que € necessario tomar esse tipo de decisdo. A forma como vyooé constréi as suas expressdes regulares dependers da sua entrada de dados e do que voce precisa fazer com essa entrada, Por fim, grupos so titeis quando usados com alternativas em conjunto com os caracteres n= cora * e§. Por | possuir a menor precedéncia dentre todos os operadores, a expresso regular “abed | efgh$ significa “case com abcd no infcio de uma string, ou case efgh no final de uma saring”. Isso é diferente de * (adea]| fg) $, que significa “case com uma siring contendo exa- tamente abcd ou exatamente efgh”, 3.2.3.6 Casamento de textos com ancoras Os caracteres * e ¢ t8m o mesmo significado nas ERBs: ancorar a expressio regular ao inicio ou ao final da string de texto (ou linha). Entretanto, existe uma diferenca significativa entre eles. Nas EREs, * ¢ ¢ siio sempre metacaracteres. Assim, expresses regulares como ab"ed © ef$ch sio vélidas, mas nao casam com nada, jé que o texto que precede 0 ~ 0 texto que scue © $ impedem 0 casamento “do inicio de uma string” ¢ “do final de uma string”, respectiva- mente. Assim como com outros metacaracteres. cles perdem scu significado especial quando utilizados dentro de expresses de colchetes. 3.2.3.7 Precedéncia de operadores em ERE A precedéncia de operadores se aplica as EREs da mesma forma que se aplica as ERBs. A tabela 3-6 mostra a precedéncia para os operadores ERE, da maior para a menor. CAPITULO 3 * Pesquisando e Substitvindo 65 Tabela 3-6 Precedéncia de operadores ERE, da maior para a menor Operader Sigificade Ll teal Gl Sinks decodes pr opuperes \necacharacter Netcare pos a Eigse cas oO Spor + i Repco do xpi reg proceere Sem into Goesensis “3 Icores I tents 3.2.4 Extensées de expressées regulares Muitos programas oferecem extensdes para sintaxe de expresses regulares. Normalmente, essas extensdes tomam a forma de uma barra invertida seguida de um caractere adicional para a.criagto de novos operadores. Isso é semelhante a0 uso de uma barra invertida em \(...\) e\{...\} nas POSIX ERBs. As extensdes mais comuns so os operadores \< ¢ \>, que casam, respectivamente, com 0 io €0 fim de uma “palavra”. Palavras sio compostas por letras, digitos ¢ 0 caractere un- derscore. Chamamos tais caracteres de componentes de palavras. O iinicio de uma palavra ocorre ou no comego de uma linha, ou no primeiro caractere de um. componente de palavra seguido de um caractere que nao seja componente de palavra. De forma semelhante, o final de uma palavra ocorre no final de uma linha, ou apés o ultimo ca- ractere componente de palavra antes de um caractere no componente de palvra. Na prética, o casamento de palavras é intuitivo e direto. A expresso regular \echop casa com chopsticks, mas nfo casa com eat a Lasbchop. Da mesma forma, a expresso regular ehop\> casa com a segunda string, mas nfo casa com a primeira. Note que \cchop\> niio casa com nenhuma das strings. Apesar de padronizada por POSIX apenas para o editor ex, 0 casamento de palavras € uni- versalmente suportado pelos editores 24, ex, vi que, por padrio, vém com todos os sistemas Unix comerciais. O casamento de palavras também é suportado nas verses “clone” desses programas, que vém com sistemas GNU/Linux ¢ BSD, assim como no enacs, vin ¢ vile. A maioria dos uilitérios GNU também o suportam. Programas Unix adicionais, que suportam. casamento de palavras, freqiientemente inclucm grep ¢ sed, mas é bom sempre verificar as paginas de manual dos comandos no seu sistema, Verses GNU dos utilitérios padrio que tratam com expressées regulares normalmente supor- tam um mimero adicional de operadores. Esses operadores so apresentados na Tabela 3-7. Tabela 3-7 Operadores adicionais da GNU para expressées regulares perder Sigicedo w Cosa com quelque crcerecomponere de plowa. Eqclenec {{:a2oun:)_} w Cesacomp cancer oto ongonate ce ona Eee [za2mums)_1 \e es cam otk fm eur pee, confeme desc crore 66 Classic Shell Scripting Tabela 3-7 Operadores adicionais da GNU para expressbes regulares (continuacao) Operadr Significedo \» sa coma sige encanta ar» coco rfl de una oie um genre desapradres\< >. Hola: Poo fat do nk so \b para represontro crore backspace, GNU awk (gavk) we \y. e esacoma signs ena ci dis cece compared ples. ve (es, sgatamen, con once fm de um feo ence. Pages GU (xere emacs) get teats tom ese cas cco cabs 0 * 5, Por fim, apesar do POSIX declarar explicitamente que 0 caractere NUL nio precisa ser ca~ sado, os programas GNU nao tém essa restri¢o. Se um caractere NUL ocorrer na entrada de dados, ele pode ser casado pelo metacaractere . ou por uma expresso de colchetes. 3.2.5 Quais programas usam quais expressdes regulares? O fato de existirem dois “sabores” diferentes de expressoes regulares é um fendmeno hist6- rico, Apesar de a existéncia do estilo egrep de express6es regulares estendidas ser conhecido durante 0 perfodo inicial de desenvolvimento do Unix, Ken Thompson nao sentiu necessidade de implementar tal pacote estendido de express6es regulares para o editor ed (dado 0 pequeno espago de enderegamento do PDP-11, a complexidade das expresses regulares estendidas, © 0 fato de que para a maioria dos trabalhos de edigfio as expressdes regulares bisicas so suficientes, essa decisio fazia sentido). O eédigo de ed servit como base para grep (grep ¢ uma abreviagio do comando ¢g/re/p do e: case globalmente re e imprima 0 casamento). O cédigo de ed também serviu de base inicial para sed. Em algum lugar no periodo pré-V7, 0 egzep foi criado por Al Aho, um pesquisador do Bell Labs que deu 0 ponta-p¢ inicial no trabalho com casamento de expressies regulares ¢ com parsers de Tinguagens. O cédigo central de casamento de egrep foi usado posteriormente ¢ reusado para expressdes regulares no programa awk. Os operadores \< e \> surgiram em uma vers4o de ed modificada por Rob Pike, Tom Duff, Hugh Redelmeier e David Tilbrook na Universidade de Waterloo (Rob Pike foi quem inven- tou esses operadores), Bill Joy, da UCB, adotou os operadores para 0s editores ex e vie, & partir dai, eles passaram a ser amplamente utilizados. Express6es intervalares tiveram sua origem no Programmer's Workbench Unix* e se infiltraram no mundo comercial do Unix através do System III e depois do System V. A tabela 3-8 lista os vérios programas Unix ¢ 0 “Sabor” de expressdes regulares eles usam, Tabela 3-8 Os programas Unix e seus tipos de expressies regulares Tips grep sod ad exivi more egrep ake «lex. me x x x x x BRE d x x \e\> x x x x 1 * Programmer's Workbench Unix (PWB) era uma variate usada dentro da AT&T para dar suporte ao desenvolvimento de ‘software para centrai tlefOnicas. Ele tamém foi cisponibilizado para uso comercial CAPITULO 3» Pesquisando e Substitvindo 67 Lex € uma ferramenta especializada, geralmente wtilizada para a construgio de analisadores léxicos para processadores de linguagens. Apesar de estar inclufda em POSIX, nao a discuti- remos mais adiantepor nao ser relevante para construcao de shell scripts. Os paginadores 1ess e pg, embora ndio fagam parte de POSIX, também suportam expressdes regulares. Alguns sistemas possuem um programa chamado page, que € essencialmente 0 mesmo que more, mas que limpa a tela entre cada troca de “pagina”. Conforme mencionamos no inicio deste capitulo, para (ou na tentativa de) mitigar o problema dos mtiltiplos programas grep, POSIX define somente um programa grep. Por omissdo, 0 grep de POSIX usa ERBs. Com a opgio -&, ele usa FREs, € com a opgao -¥, ele usa 0 algo- ritmo de string fixa do ¢grep. Assim, os programas verdadeiramente de acordo com POSIX uusam grep -2 .. em vez de egrep .... Porém, ja que todos sistemas Unix o tem, e provavelmen- te continuario tendo pelos préximos anos, continuamos a usé-lo em nossos scripts Uma titima observacdo € que, tradicionalmente, awk no suportava expressdes intervalares no seu “sabor” de expresses regulares. Mesmo em 2005. 0 suporte para expressdes intervalares, ainda ngo era universal entre as diferentes versdes comerciais do awk. Para portabilidade mé- xima, se vocé precisa casar as chaves em um programa awic, voc8 deve protegé-las com uma barra invertida, ou enclausuré-las dentro de uma expressio de colchetes. 3.2.6 Fazendo substituiges em arquivos texto Muitas tarefas de shell scripts comecam pela exiragao de texto de interesse, usando grap ou grep. Os resultados iniciais de uma pesquisa de expressoes regulares ento passam a ser os dados “crus” para um posterior processamento. E comum que pelo menos um passo consista tna substituiedo de texto — ou seja, substituir uma parte do texto por alguma outra coisa, ou remover uma parte do texto da linha que casou. Na maior parte do tempo, o programa certo para se usar em substituigées de texto € sed, 0 Editor de Streams. sed foi projetado para editar arquivos na forma de lotes, ao invés de inte rativamente. Quando voc® sabe que tem muitas substituigGes para fazer, seja em um ou varios arquivos, € muito mais facil escrever as mudangas em um script de edigao e aplicar o script a todos os arquivos que precisam ser modificados — e sed serve a esse propésito, (Apesar de ser possfvel escrever scripis de edicdo para uso com os editores de linha ed ou ex, fazé-los & mais, complicado, e também é muito mais diffeil de (lembrar de) salvar o arquivo original). Achamos que, para shell scripts, 0 principal uso de sed é fazer simples substituigdes de texto, por isso abordaremos esse tema primeiro. Traremos, entéo, algumas informagées e explica- g6es adicionais sobre as capacidades de sed, mas propositalmente no entraremos em muitos detalhes. sed € descrito com toda sua gléria no livro sed & awk (O'Reilly) 04 GNU esté dispontvel em fip:/fip,gnu.org/gnu/sed/. Ele possui algumas extensOes interes- santes que s30 documentadas no manual que o acompanha, O manual de GNU sed também. contém alguns exemplos interessantes, e a distribuigao inclui um conjunto de testes com programas pouco comuns. Talvez o mais impressionante seja a implementagdo de de, uma calculadora de precisdo arbitréria do Unix escrita como um script sea! Uma excelente fonte para todas as coisas relacionadas a sea ¢ hutp://sed. sourceforge.nev/. Bla inclui Tinks para dois documentos de perguntas freqiientes (FAQs) sobre sed na Internet. 0 primeiro esté dispontvel em hitp://vww.dreamwurcom/sed-info/sed-faq.himl 0 segundo, € também mais antigo, encontra-se em jip.//rfm.mit.edu/pubjfags/editor-fag/sed. 68 Classic Shell Seripting sed Uso sed [ -n ] 'comando de edigao' [ arquivo ... } sed [ -n ] -2 ‘comando de edigao' ... [ arquivo... ] sed ( -n ] -f arquivo-script ... { arquivo ... } Propésito Para editar 0 stream de entrada, produzindo resultados na safda padrio, 20 invés de modificar os arquivos da forma como um editor interativo faria. Ape- sar de sed ter muitos comandos e poder fazer coisas complicadas, seu uso mais comum para realizar substituigdes de texto em um stream de entrada, geralmente como parte de um pipeline, Princpais op¢oes ~e 'comando de edicdo! Use 0 conando de edigao na entrada de dados. -e deve ser usado quan- do existem miltiplos comandos, -f arquivo-script Leia os comandos de um arquivo script. Isso é util quando hé muitos ‘comandos para se executar. Suprima a impressio normal de cada linha modificada. Em vez disso, as linas devero ser impressas explicitamente com 0 comando p. Comportamento Lé cada linha do arquivo de entrada, ou da entrada pada se no for pasado nenhum arquivo. Para cada linha, sed executa todos os comandos de edi- ¢¢do que se aplicam a linha de entrada. O resultado ¢ escrito na saida padrao (Como regra geral, ou caso seja explicitamente definido com 0 comando p e a opciio -n), Sem as opcdes -e ou -f, sed trata o primeiro argumento como o conando de edicdoa ser utilizado. 3.2.7 Uso basico Na maior parte do tempo, voce usard sed no meio de um pipeline para fazer substituigdes. Isso é feito com 0 comando s, que pega uma expresso regular para procurar um texto de substituig#o que serd colocado no lugar do texto casado e alguns flags opcionais: eed 's/:.*//' /eto/pasews | ‘Remove tudo depots do primeiro caractere “dos-pontos” sort -u (Ordena a lista ¢ remove as duplicatas Aqui, o caractere / age como um delimitador, separando a expressio regular do texto de subs- tituicdo. Nessa insténcia, o texto de substituigo € vazio (a famosa string nula), que apaga o texto casado. Apesar de / ser 0 delimitador mais comum, qualquer caractere vis(vel pode ser utilizado. Ao se trabalhar com nomes de arquivos, € comum o uso dos caracteres de pontua- 40 como delimitadores (tais como o dois-pontos, ponto-e-virgula, ou virgula) find fnone/tolstey -type 4 -print | Encontra todos dieéris sed 's;/hone/tolstoy/;/bome/Lt/;' | Trocao nome; observe o uso de ponto-e-vrgula como delinitador sed 's/*/nkdir /* | Insere 0 comand mkdir sh -x Execida com rastreamento (tracing) do shell CAPITULO 3 © Pesquisando e Substitvindo 69 Esse script cria uma c6pia da estrutura de diret6rios de /hone/tolstoy para /none/ Le (talvez em preparacio para fazer backup). (O comando find € descrito no Capitulo 10. Sua saida, nesse caso, é uma lista de nomes de diretérios, um por linha, com todos diret6rios abaixo de /oone /coistoy). O seript usa o interessante truque de gerar os comandos ¢ endo alimentar a cadeia de comandos como entrada para o shell. Essa é uma técnica poderosa e geral que no € tao usada como deveria.* 3.2.7.1 Detalhes de substituigio ‘4 mencionamos que qualquer delimitador além de barras pode ser usado. Também é possivel proteger 0 delimitador dentro da expresstio regular ou do texto a ser substi pode tornar a leitura bem mais dificil: sed '8/\/none\/tolstoy\//\Jhone\/1t\//" Anteriormente, na Seto 3.2.2.2, ao descrevermos as POSIX ERBs, mencionamos uso de referéncias para trés nas expressdes regulares, ced entende referéncias para trés. Além disso, elas podem ser usadas no texto de substituigdo para significar “substitua neste ponto 0 texto casado pela n-ésima sub-expressio entre parénteses”. § echo /home/tolstoy/ | sed 's;\(/home\) /tolstoy/i\1/1t/s" /hone/1t/ sed substitui \1 pelo texto que casou com a parte /hone da expressio regular. Nesse caso, todos os caracteres sio literais, mas qualquer expressio regular pode ser colocada entre \(€ \). Siio permitidas até nove referéneias para trés Alguns outros caracteres também so especiais na substituig20 de texto. J4 mencionamos a necessidade de proteger com a barra invertida 0 caractere delimitador. Como seria de esperar, isso também ¢ necessario para 0 préprio caractere barra invertida. Finalmente, 0 & na substi- tuigio de um texto significa “substitua neste ponto todo o texto casado pela expressio”, Por exemplo, suponha que trabalhemos para a Camara do Comércio de Atlanta, ¢ precisamos trocar nossa descrigiio da cidade em todos os lugares no nosso folheto: ny atlga.xml atiga.xml.old sed 's/atlanta/é, the capital of the South/* < atlga.xml.old > atiga.xel (Sendo uma empresa modema, usamos XML sempre que podemos, 20 invés de processado- res de textos caros e proprietirios). Esse script salva o arquivo original do folheto, como um backup, ¢ entio aplica a mudanga com se. Fazer algo desse tipo é sempre uma boa idéia, principalmente quando voc ainda esté aprendendo a trabalhar com expresses regulares substituicdes, Para ter 0 caractere & no texto de substituigdo, proteja-o com barra invertida, Por exemplo, 0 pequeno script a seguir pode ser usado para transformar barras invertidas em arquivos Doc- Book/XML nas entidades DocBook sso) correspondentes sed '9/\/\kbe0:/3" O sufixo g no comando s anterior significa global. Isso 6, “substitua todas ocormréncias da expressio regular pelo texto de substituiggo”, Sem ele, sed substituiria apenas a primeira ocorréncia, Compare os resultados dessas duas invocagdes, com e sem 0 g * Esse script tem uma faba: cle no pode trata dretérios cujos nomes possuem expages. [sso pode ser resolvide com téenicas ‘que ainda nto vimos; veja Capitulo 10. 70 _ Classic Shell Scripting § echo Tolstoy reads well. Tolstoy writes well. > exanple.txt Etemplode entrada § sed 'e/Tolstoy/Camus/" < example. txt Sem" Camus xeads well. Tolstoy writes well $ sed ‘s/Tolstoy/Camus/g* < example.txt Cons" Camus reads well. Camus writes well. Um detalhe pouco conhecido (impressione seus amigos!) & que voc8 pode colocar um ntime- ono final, indicando qual ¢ a n-ésima ocorréncia que deve ser substitufda’ $ sed 'e/Tolstoy/Camus/2' < example.txt — Apenas.a segunda ocoréncia Tolotoy reado vell. Carus writes vell. Aré aqui, fizemos apenas uma substituig#o por vez. Apesar de voc# poder encadear varias, instancias do sed_em um pipeline, € mais facil dar mitliplos comandos a se4. Na linha de comando, isso é feito utilizando-se a opgao -e. Os comandos so fornecidos através da opco -e, sendo um -e para cada comando: sed -e '6/foo/bar/g' -e 'e/chicken/cow/g' myfile.snl > nyfile2.xnl No entanto, quando vocé tem mais do que umas poucas edigdes, essa forma toma-se ente~ diante. Em algum momento, € melhor colocar todas suas edges em um arquivo script, © entio executar sed com 0 uso da opgio -£: § cat Sup.ced 8/fo0/bar/g s/chicken/cow/g s/draft animal/horse/g $ sed -£ fieup.sed myfile.sm) > myfile2.xml Voce pode construir um script pela combinagao das opgdes -e & -£; 0 script éa concatenagéio de todos os comandos de edigio fornecidos por todas as opgdes na ordem dada. Adicional- mente, POSIX permite que voc8 separe 0s comandos na mesma linha, utilizando um ponto- e-virgula: sed 's/foo/bar/g ; s/chicken/cow/g myfile.xcrl > myfile2 xml Porém, muitas versées comerciais do sed (ainda) no permitem que isso seja feito, portanto melhor evitar seu uso para portabilidade absoluta, Como seu antecessor e e seus primos ex e vi, sea lembra da vitima expresso regular usada em qualquer ponto em um script. Essa mesma expresso regular pode ser reusada pela espe- cificago de uma expressio regular vazia 8/fo0/bar/3 Troca0 tercir foo 8/fqaux/ Agora trocao primeiro Considere um script direto chamado html2xhtml.sed para fazer uma conversao inicial de HTML para XHTML. Esse script converte as marcas para mintisculas ¢ troca a marca
na forma de autofechamento
: s//ehi>/g A barra como deliniador 8//

/ 8//g 8///e §/
/
/5 8/
/
/g s::iig CAPITULO 3» Pesquisando e Substitvindo 71 er e2 : aaa <[AS>+ ::g /<(ith) (7) (Ma) [LL] >: s 98:: :
:g Tal script pode automatizar uma grande parte da tarefa de converter HTML para XHTML, a verso padronizada e baseada em XML do HTML. 3.2.8 A operasdio de sed A operagiio de sed € direta. Cada arquivo chamado na linha de comando é aberto ¢ lido um por vez. Se no existem arquivos, a entrada padrao é utilizada e o nome de arquivo “-” (um \inico hffen) age como um pseudOnimo para a entrada padrao, sed Ié uma linha por vez de cada arquivo. A linha ¢ colocada em uma érea de meméria cha- mada de espaco do padrio. Isso é semelhante a uma variével em uma linguagem de progra- magao: uma rea de meméria que pode ser modificada conforme solicitado, sob orientagao dos comandos de edigo. Todas as operagtes de edigZo sZo aplicadas 20 contetido do espago do padrao. Quando todas tiverem sido completadas, sed imprime 0 contesido final do espago do padro na safda padrio, e entZo volta para o inicio, para ler uma outra linha de entrada. Essa operagdo é mostrada na Figura 3-2. O script usa dois comandos para trocar The Unix Systenem The Unix Operating Systen, TieeicSen Sct Sai /ONTX/ S/ONIK Systen/INZX Operating Systen/ Toc oergpx0 Figura 3-2 Comandos em scripts s24 modificondo o espace do padréo. 72__Classic Shell Scripting 3.2.8.1 Imprimir ov ndo imprimir A opgio -n modifica 0 comportamento padrio do sed. Quando fornecida, sed ndo imprime © contetido final do espago do padriio ao terminar sua execucdo. Em vez disso, comands p 1no script imprimem a linha explicitamente. Por exemplo, alguém pode simular 0 grep da seguinte forma: sed -n '/cHIMi>/p' * html Inprime apenas lina com Apesar dese exemplo parecer trivial, esse recurso ¢ titi] em scripts mais complicados. Se vocé usa um arquivo de seript, pode habilitar esse recurso pelo uso de uma primeira linha especial: fm Deslga impressio auiordtca /<8TML2/p Inprioe apenas lnhas com Como no shel! e em muitas outras linguagens script de Unix, o #¢ um comentario. Comenté- rios sed deve aparecer em linhas préprias, j4 que, sintaticamente, eles sio comandos — eles apenas so comandos que no fazem nada. Enguanto o POSIX indica que os comentirios podem aparecer em qualquer lugar em um script, muitas verses antigas do sea permitem que eles aparegam apenas na primeira linha, O ced da GNU nao tem essa limitagtio. 3.2.9 Casando com linhas especificas Conforme mencionado, por padro sea aplica todo comando de edigo para todas linhas de entrada. E possivel restringir as linhas para as quais o comando se aplica, pré-fixando 0 co- mando com um enderego. Assim, a forma completa de um comando sed é: endereco conando Existem tipos diferentes de enderegos: Expressoes regulares Pré-fixando um comando com um padrao, limita 0 comando as linhas que casam com 0 padrio. Isso pode ser feito com 0 comando st Jolatune/ s/3/# 101: migrate to newfunc/ —_Comeniar um cdlifo foe Um padriio vazio no comando « significa “use a expressio regular anterior”: ITolstoy/ 8//é and Cams/g Falar sobre dois autores Altima tinha O simbolo $ (como no ed ¢ ex) significa “a dltima linha”. Por exemplo, este script é uma forma rapida de imprimir a Gitima linha de um arquivo: sed -n '$p" "$1" ‘Necessdro prteger com aspas,conforme é mosirado! Para eed, a “ultima linha" significa a iltima linha de entrada. Mesmo quando processando miltiplos arquivos, sed os vé como um longo stream de entrada e $ se aplica apenas 2 il- tima linha do titimo arquivo (sea GNU possui uma opefo que faz. com que 0s enderegos se apliquem separadamente a cada arquivo; veja a documentaco). Niémeros de linka ‘Vocé pode usar ntimeros de linha absolutos como enderegos. Um exemplo ser fornecido em seguida. CAPITULO 3 * Pesquisando e Substitvindo 73 Faixas ‘Voce pode especificar uma faixa de linhas separando os enderegos com uma virgula: sed -n '10,42p! foo. xml Iprina apenas as linhas 10-82 1d '/f00/, /bar/ ¢/baz/quux/g! -Faga a substitugdio apenas na fixe de linhas segundo comando diz “inicie com linhas casando foo e continue com linhas que casem com bar, substitua todas ocorréncias de baz por quux.” (Ieitores familiarizados com ed, ex, 0v 0 prompt “dois-pontos” do v: reconhecerdo essa forma de uso). uso de duas expressdes regulares separadas por virgulas € chamado de expresso de faixa, No se4, isso sempre inclui pelo menos duas linhas, Expresses regulares negadas Ocasionalmente, ¢ til aplicar um comando a todas linhas que néio casam com um padi em particular. Isso pode ser especificado adicionando-se um caractere ! apés uma expres- so regular para procurar por: /ased/ |8/new/used/g Troca new por used nas linhas que nao casam com used padre POSIX indica que o comportamento € “no especificado” quando um espago em branco segue 0 1, ¢ recomenda que aplicagdes completamente portaveis nao colo- quem nenhum espaco depois dele. Aparentemente, isso deve-se a algumas verses hist6- ricas de sed que nao permitiam esse comportamento. O Exemplo 3-1 apresenta uma versdo simples do programa head usando sed, demonstrando 0 uuso de niimeros de linhas absolutos como enderegos. Exemplo 3-1 Uma versdo do comando head usando sed 4 head --- inprine as primeiras a Linhas ' # usage: head N arquivo count=$1 sed §{count}q "$2" Quando invocado como head 10 foo. x1, sed acaba sendo invocado como sed 10g 00.1 0 comando q faz. com que 0 sed saia imediatamente; nenhuma entrada seguinte € lida ou comandos sio executados. Mais adiamte, a Seco 7.6.1, mostraremos como fazer esse script parecer mais com o verdadeiro comando head. Conforme vimos até agora, sed usa caracteres / para delimitar padrées de pesquisa. Porém, hé proviséo para o uso de diferentes delimitadores nos padrées. 1ss0 & feito precedendo-se 0 caractere com uma barra invertida: $ grep tolstoy /etc/passnd Mostra a linha original tolstoy:x:2076:10:Leo Tolstoy: /hone/tolstoy: /bin/bash § sod -n '\:tolstoy: 0; ;Toletoy;p' /ote/pacowd Fazamudanga Tolstoy:x: 2076: 10:Leo Tolstoy: mnone/telstoy:/bin/baeh Nesse exemplo, 0 dois-pontos delimita 0 padrio para pesquisar por, ¢ o ponto-c-virgula age como delimitador para o comando s. A operagio de edi¢do, por si s6, é trivial; nosso ponto aqui € demonstrar o uso de diferentes delimitadores, no fazer a substituicao por sua prépria importncia, 7A__ Classic Shell Scripting 3.2.10 Quanto texto é modificado? ‘Uma questio que ainda nao discutimos “quanto texto se casa?” Na verdade, existem duas questées, © a segunda € “onde o casamento comega’?”. De fato, quando se esté fazendo pes- quisas de texto simples, como com grep ou earep, por exemplo, ambas questies séo irrele- vantes. Tudo 0 que voc8 quer saber é se a linha casou:; se sim, voc vai querer ver a linha, Em que ponto na linha 0 casamento comega, ou até onde ele se estende na linha realmente nao importa, Saber a resposta para essas questdes, porém, se torna vital quando se faz substituigao de texto com 0 sed ou programas escritos em awk (apesar de no abordarmos edicao de texto neste livro, entender isso também ¢ importante para o uso no dia-a-dia quando quando se esté tra- balhando dentro de um editor de textos). A resposta para ambas questdes € que uma expressio regular casa a substring mais longa € mais @ esquerda da entrada de texto que pode casar com a expressio inteira. Além disso, um casamento de uma string nula é considerado mais longo que qualquer outro casamento (as- sim, conforme explicamos anteriormente, dada uma expresso regular abc, casando com 0 texto ac, 0 b& casa com sucesso com a string nula entre a € c). Também, o padrio POSIX diz: “Sendo casamento completo o mais longo dos casamentos mais a esquerda, cada subpa- dro, da esquerda para a direita, deve casar com a string mais longa possivel.” (‘Subpadries, sto as partes envolvidas por parénteses em uma ERE. Para esse propésito, os programas GNU seguidamente estendem ese recurso para \(...\) nas ERBs também). Se sed est substituindo o texto casado por uma expresso regular, 6 importante ter certeza de que uma expressio regular no casa pouco ou muito texto. Eis um exemplo simples: $ echo Tolstoy writes well | sed 's/Tolstoy/cams/* Use sings fas Camus writes well E claro que sed pode usar expressdes regulares completas, ¢ é nesse ponto que entender a “mais longa e mais a esquerda” se torna importante: $ echo Tolstoy is worldly | sed ‘s/T.*y/Camas/* Tente una expressiio regular camus 0 que acomeceu? Aparentemente, a intengio era casar apenas ‘folstoy. Porém, jd que o casamento se estende para a quantidade de texto maior possivel, ele seguiu até encontrar oyem worldly! Assim, se faz necesséiria uma expresso regular mais refinada: § echo Tolstoy is worldly | sed ‘s/T[{:elpha:]]*y/Camus/* Canus is vorldly Em geral, ¢ especialmente se vocé esté ainda aprendendo as sutilezas das expresses regula- res, ao desenvolver scripts que fazem muitas modificagdes em textos, vocé vai querer testar as, coisas com muito cuidado e verificar cada passo conforme eles S40 escritos. Finalmente, conforme vimos, possivel casar a string mula ao fazer busca de texto. Isso tam- bem € verdade quando se faz substituigdo de texto, permitindo que vocé insira 0 texto: $ echo abe | sed 's/bt/1/* Subst oprineir casamento abe § echo abo | sed '9/b#/1/g Subst odoscasamentos daict Note como b* casou com a siring nula na frente e depois de abe. CAPITULO 3 * Pesquisando e Substitvindo 75 3.3 3.2.11 _Linhas versus strings E importante fazer uma distingio entre linhas e strings. A maioria dos programas simples tra- balham em linhas de entrada de dados. Isso inelui grep, earep €, 99% do tempo, sed. Em tal caso, por defini¢o nao haverd nenhum caractere de nova linha embutido nos dados que esto sendo casados, ¢ * ¢ $ representam o inicio ¢ o fim da linha, respectivamente, Porém, linguagens de programacdo que trabalham com expresses regulares, tais como avk, Perl e Python, geralmente trabalham com strings. Pode ser que cada string represente uma Unica linha de entrada, nesse caso * e § ainda representam o inicio e fim da linha, Essas lin- guagens, no entanto, permitem que voc’ use diferentes formas para especificar como os regis tros de entrada serdo delimitados, abrindo a possibilidade de que uma tinica linha de entrada (.e., registro) possa ter caracteres de nova linha embutidos; eles representam apenas 0 inicio © o fim de uma string. Vale a pena ter esse ponto em mente quando vocé comegar a usar mais, ferramentas de software programéveis. TRABALHANDO COM CAMPOS Para muitas aplicagdes, é produtivo ver seus dados consistindo de registros e campos. Um. registro é uma tinica colegio de informagtes relacionadas, assim como uma empresa teria com um cliente, fornecedor, ou empregado, ou que uma escola teria com um estudante, Um campo é um componente nico de um registro, assim como o tltimo nome, o primeiro nome, ou ara do endereco. 3.3.1 Convengées de sistemas de arquivos Pelo fato do Unix encorajar 0 uso de dados textuais, é comum armazenar dados em um ar- quivo texto, com cada linha representando um tinico registro. Existem duas convengées para separar 05 campos uns dos outros dentro de uma linha. A primeira é usar apenas espagos em. branco (espagos ou tabs): § cat myapp.data # model unidades vendidas vendedor xii 23 jane 45 2 joe cats 65 chris Nesse exemplo, linhas comegando com um caractere # representam comentitios, e sio ig- noradas. (Essa € uma convencio comum. A habilidade de ter linhas de comentiios ¢ util, ‘mas requer que 0 seu software seja capaz de ignorar tais linhas.) Cada campo ¢ separado do préximo por um niimero arbitrétio de caracteres espaco ou tab. A segunda convencio ¢ usar uum caractere delimitador em particular para separar os campos, como o dois-pontos: $ cat myapp.data # nodel:unidades vendidas:vendedor 11:23 jane rjA5:12:}08 cate:es:enris Cada convengao tem vantagens e desvantagens. Quando o espago em branco é o separador, € dificil de ter espagos em brancos reais dentro do contetido dos dados (se voce usar um tab como separador, voce pode usar um caractere espago dentro de um campo, mas isso é 76 _ Classic Shell Scripting visualmente confuso, j4 que no se pode facilmente ver a diferenga somente olhando para © arquivo). Por outro lado, se voc® usar explicitamente um caractere delimitador, torna-se dificil incluir esse caractere nos seus dados, Freqiientemente, porém, é possivel fazer uma escolha cuidadosa, de forma que a necessidade de incluir um delimitador se torma minima ou inexistente, f=) Uma diferenga importante entre as duas abordagens tem a ver com as multiplas £5 4. ocorréncias dos) caractere(s)delimitador(es). Quando se usa espagos em bran- © 43 co, a comvengio éque sucessivas ocontneias de expagos ou fabs agem como um tinico delimitador. Porém, quando se usa um caractere especial, cada ocorréncia separ wm campo. Assi, per eromple dots corctereedos-ponine ua vgvad versio do nyapp.cata (um :;") delimitam um campo vazio, O principal exemplo da abordagem de campos separados por caractere delimitador é 0 fete/ passwd. Existe uma linha por usuério do sistema e os campos so separados por dois-pontos. Usamos /etc passwd para muitos exemplos ao longo do livro, j4 que um grande néimero de tarefas administrativas de sistema envolvem ele, Aqui esté uma entrada tipica: tolstoy:x:2076:10:Leo Tolstoy: /home/tolstoy:/bin/bash Os sete campos dos registros em um arquivo de senhas si 1. Onome de login. 2. A senha criptografada (que pode ser um asterisco se a conta est desabilitada, ou possi- velmente um caractere diferente se as senhas criptografadas esto armazenadas separa- damente em /ete/ shadow). 3. Ontimero ID do usuario. 4. O ntimero ID do grupo. 5. O nome pessoal do usuério ¢ possivelmente outros dados relevantes (ntimero do escrité- rio, nimero de telefone, ete.). 6. O diretério home. 7. O shell de login. Algumas ferramentas Unix trabalham melhor com campos separados por espagos em branco, outras com campos separados por um delimitador, ¢ alguns utilitérios se adaptam as duas, formas, trabalhando com qualquer tipo de arquivo, conforme veremos. 3.3.2. Selecionando campos com cut O comando cut foi projetado para cortar dados de arquivos texto. Ele pode trabalhar baseado em campos ou em caracteres. A primeira forma ¢ til para eliminar determinadas colunas de lum arquivo. Tenha cuidado, pois um caractere tab conta como um Unico caractere!* Por exemplo, o comando a seguir imprime o nome de login ¢ 0 nome completo de cada usué- rio do sistema: $ cut -¢ + -£ 2,5 /ete/pasewa Ext campos root :x00t Cons adinistatvas * Isso pode ser contornado com expand e unexpand: vejaas piginas de manual de expand) CAPITULO 3» Pesquisando ¢ Substitvindo 77 cut Uso cut -c list [ file... 1 cut -£ list [ -d delim) [ file... | Propésito Sclecionar um ou mais campos ou grupos de caracteres a partir de um arquivo de entrada, supostamente para um posterior processamento em um pipeline. Principais opcoes -c lista Corte baseado em caracteres. 1ista é uma lista separada por virgulas de nimeros ou faixas de caracteres, como 1,3,5-12,42. -d dein ‘Use delim como delimitador com a opgio -£. O delimitador padrio € ‘ocaractere tab. -f Lista Corta baseado em campos. 1isca é uma lista de niimeros, de campos ‘ou faixas separada por virguilas. Comportamento Corta os campos nomeados ou faixas de caracteres de entrada. Quando pro- cessando campos, cada caractere delimitador separa os campos. Os campos de safda so separados pelo caractere delimitador dado. Lé a entrada padrao se nenhum arquivo for passado na linha de comando, Veja o texto para exemplos, Detalhes Em sistemas POSIX, cut. entende caracteres multi-byte. Assim, “caractere” no é sinénimo de “byte”. Veja as paginas do manual do cut(1) para detalhes. Alguns sistemas tem limites no tamanho da linha de entrada, particularmente quando caracteres multi-byte estio presentes. tolstoy:teo Tolstoy Usuarios exisientes austen:Jane Austen canus:Albert Camus Ao escolher um ntimero diferente de campo, podemos extrair o diretério home de cada ususrio: $ out -d : -f 6 /etc/passud Extra diretbrio home Jr0ot Contas adminstratvas Jnome/tolstoy Usados exisienes /nome/austen ‘Thome/camas Cortar por lista de caracteres pode, ocasionalmente, ser ttil. Por exemplo, para retirar apenas 8 campos de permissio de 1s -1: $le-1 | cut -c 1-10 78__ Classic Shell Scripting total 2678 Porém, isso € mais arriscado que usar campos, ja que néo ha garantias de que cada campo em uma linha tera sempre a mesma largura em todas linhas, Em geral, preferimos comandos baseados em campos para extragio de dados, 3.3.3 Unindo campos com join comando join permite que vocé una arquivos em que os registros de cada arquivo com- partilham uma chave comum — isso é, 0 primeiro campo de um registro, Chaves sio freqiien- join Uso join [ options ... ] filel file2 Propésito Unir registros em arquivos ordenados com base erm uma chave comum. Principais opgoes “1 campo -2 campo? Especifica os campos sobre os quais a unio deve ser feita. -2 campo specifica canpot de arquivol, € -2 campo2 especifica canpo2 de ar- quivo2, Campos so numerados a partir do néimero um, no de zero. ~0 arquivo. campo Faz com que a saida seja composta pelo campo canpo do arquivo ar- gaivo. O campo comum ndo € impresso, a menos que seja requisitado explicitamente. Use miiltiplas opgdes -o para imprimir miltiplos cam- pos de safda, -t separador Em vez de usar espagos em branco, use separacer como 0 separador de ‘campos de entrada. Esse caractere se toma 0 separador de campos de sada também, Comportamento Lé arquivol ¢ arquivo? unindo os registros baseados em uma chave comum, Exccuta usando espagos em branco como separador de campo. A saida con siste de uma chave comum, o resto do registro de arquivot, seguido pelo resto do registro de arquivo? Se arquivoi € -, 0 join lé a entrada padrio. O primeiro campo de cada arquivo € a chave padrao sobre o qual a unigo sera executada; isso pode ser trocado com -1 ¢ -2. Linhas sem chaves em ambos arquivos nao serio impressas por omissio. (Existem opges para modificar sso; veja as paginas de manual para join(1) ). Detalhes As opges -1 € -2 sio relativamente novas. Em sistemas mais antigos, voce pode precisar usar -j1 campot ¢ -32 campo2. CAPITULO 3 * Pesquisando e Substitvindo 79 temente coisas como nomes de usuétro, tiltimo nome pessoal, mimeros ID de funcionérios, assim por diante. Por exemplo, vocé pode ter dois arquivos, um que lista quantos itens um, vendedor vendeu ¢ um que lista a quota do vendedor: $ cat sales ‘Mostra o arquivo de vendas # dados de venda Comentéries explicativas # quantidade por vendedor jee 100 jane 200 herman 150 chris 300 § cat quotas Mostra o arquivo de quotas # quotas # quota do vendedor joe 50 jane 75 herman 60 chris 95 Cada registro possui dois campos: 0 nome do vendedor ¢ a quantidade correspondente. Nesse caso, existem miéltiplos espagos entre as colunas de forma que eles se alinhem corretamente. Para que join funcione corretamente, 05 arquivos de entrada devem primeiro ser ordenados. O programa no Exemplo 3-2, nerge-cales.ch, une dois arquivos usando 0 join. Exemplo 3-2 nerge-sales.sh H! /bin/eh 4 merge-sales.sh 4 # Conbina dados de quota e de vendas 4 Remove os comentarios e ordena ce campos de dados sed '/*#/a" quotas | sort > quotas.sorted sed '/*#/" sales | sort » sales.sorted # Conmbina pela primeira chave, os resultados so enviados para a saida padrao join quotas.sorted sales.sorted # Renove arquivos tenporarios mn quotas.sorted sales.sorted O primeiro passo é remover as linhas de comentério com 0 sed, e entio ordenar cada arquivo. Os arquivos temporarios ordenados se tornam a entrada para o comando Join, ¢ finalmente © script remove os arquivos temporérios. Abaixo, vemos o que acontece quando ele executa: § . morge-sales.sh chris 9§ 300 herman 60 150 jane 75 200 jee 50 100 3.3.4 Rearranjando campos com o awk ank & uma linguagem de programacio itil por si s6. Na verdade, dedicamos o Capitulo 9 para tratar das partes mais importantes da linguagem. Apesar de voce poder fazer bastante coisas 80__Classic Shell Scripting com awk, ele foi propositalmente projetado para ser itil na programagao de shell scripts — fa zer manipulagées simples de texto, tais como extragio ¢ rearranjo de campos. Nesta segio, examinaremos 0 bésico do axk de forma que vocé possa entender os “programas de uma linha"** quando os vir. 3.3.4.1 Padrées e asies O paradigma bisico de ave € diferente de muitas linguagens de programagio. Ele é semelhan- tes em diversos aspectos @ sed: avk ‘programa’ [ arquivo ... | O aur 18 um registro (linhas) por vez de cada um dos arquivos nomeados na linha de comando (ou na entrada padrao se nenhum arquivo for passado). Para cada linha, ele aplica os coman- dos conforme o especificado pelo programa para a linha, A estrutura bésica de um programa ak padrio { ago } padrao { agao } A parte padsao pode ser quase qualquer expresso, mas em “programas de uma linha”, cla 6 tipicamente uma ERE cercada por barras. Jé a aco pode ser qualquer comando awk, mas em “programas de uma linha” ela étipicamente um comando print: limpo (veja os exemplos mais adiante). Tanto o padro quanto a agdo podem ser omitidos (mas, € claro, ndo ambos). Um padro omitido faz com que a ago seja executada em todos os registros de entrada, Uma ago omi- tida ¢ equivalente a { print }, que, como veremos em seguida, imprime o registro inteiro. A maioria dos “programas de uma linha” tém a forma: | awk *{ print sone-stuft }* | Para cada registro, awk testa cada padrao no programa. Se o padrao for verdadeiro (por exem- plo, o registro casa com a expressiio regular, ou a expressio geral o avalia como verdadeito), entiio auk executa 0 c6digo da agtio. 3.3.4.2 Campos aank possui campos ¢ registros como uma parte central de seu projeto. Ele Iéregistros de en- trada (geralmente apenas linhas) ¢ automaticamente quebra cada registro em campos. evk, entio, define @ varivel interna? para o ntimero de campos em cada registro. Por padrao, espagos em branco separam campos — ou seja, funciona por espagos e/ou carac- teres tab (como join). Isso &, geralmente, o que vocé quer fazer, mas existem outras opcdes. Definindo a varidvel FS como um valor diferente, voc’ pode mudar a forma como awk separa 05 campos. Se vocé usar um Gnico caractere, entdo cada ocorréncia desse caractere separa os campos (como cut ~d). Também é possivel, ¢ aqui é que avis se destaca, defini-lo para ERE completa e nesse caso, cada ocorréncia de texto que casa com a ERE funciona como um se- parador de campo. "> N. deT. Em inglés o termo one-liners € empregado nesse sentido. CAPITULO 3» Pesquisando.e Substitvindo 81 Valores de campos foram projetados como tal, com o caractere §. Geralmente, $ € seguido de ‘uma constante numérica. Porém, ele pode ser seguido de uma expresso; mais comumente 0 nome de uma varidvel. Aqui esto alguns exemplos: awk '{ print $1}! Imprime os campos sem padrio) awk '{ print $2, $5 )* Imprime o segurdo eo guinio campos (sem padirio) awk '{ print $1, §NF }! Inprime oprineiro ¢ timo campo (sem padréo) avk ‘NF > 0 { print $0 }* Inprimelinhas nd vaias (pads a0) awk 'NF > 0! O mesmo que oacinel sem ago, 0 padrio¢ imprimir) Um caso especial ¢ 0 nimero de campo zero, que representa 0 registro completo. 3.3.4.3 Especificando separadores de campo Para programas simples, voc8 pode trocar 0 separador de campo com a opcfo -F. Por exem- plo, para imprimir o nome de usudrio e 0 nome completo a partir do arquivo /ete/passwa: § ave -P: ‘{ print $1, 95 }* /ete/pasend —Processa0 /etepassvd root root Contas annisratvas tolstoy Leo Tolstoy Usudrios nommais, austen Jane Austen canus Albert Camus A opgdoo -F define automaticamente a varidvel FS. Note como o programa ngo precisa fazer referéncia a FS diretamente, nem ele tem que gerenciar a leitura dos registros e divi campos; 0 awk Faz isso tudo automaticamente. Vocé pode ter notado que cada campo da safda € separado com um espaco, mesmo que o separado de campos de entrada seja um dois-pontos. Diferentemente de todas as outras ferra- mentas, avk trata 03 dois separadores distintamente um do outro. Vocé pode mudar 0 separa- dor de campos de safda definindo a varidvel ors. [ss0 pode ser feito na linha de comando com a opi -v, que define as varidveis do awk. O valor pode scr qualquer string, Por exemplo: $ avk -F: -v toFS=H#" {print $1, $5 }' /etc/passwd Proves o/ee/passnd root*#ro0t Cons dranistratvas toletoy**ie0 Tolstoy Usuérios norms austen**Jane Rusten camus**Albert Camas \Veremos, resumidamente, que existem outras formas de definir essas varidveis. Elas podem ser mais legtveis dependendo do seu gosto. 3.3.4.4 Imprimindo linhas Conforme mostramos até agora, na maior parte do tempo voeé s6 quer imprimir campos sele~ cionados ou arranjé-los em uma ordem diferente. A impressio simples ¢ feita com o comando print. Voc fomnece a ele uma lista de campos, variaveis ou strings para imprimir: 82__ Classi Shall Seripting § avk -P: '{ print "User*, $1, "is really", $5 }' /ete/pasewd User root is really root User tolstoy is really teo Tolstoy User austen is really Jane Austen User camus is really Albert Camus Um comando print limpo, sem nenhum argumento, é equivalente ao print $0, que imprime o registro inteiro. Para casos como 0 exemplo recém mostrado, quando vocé quer misturar texto ¢ valores, geralmente € mais limpo usar a verséo do avi do comando print. Ele é suficientemente pa- recido com a versio do shell (¢ C) descrita na Segio 2.5.4, para que nao entremos em detalhes novamente, Aqui esté o exemplo anterior, usando print: § awk -F: '{ printe " $1, $5)! /etc/passwa User root is really root cas is really 4e\n User tolstoy is really Leo Tolstoy user austen is really vane Austen User caus is really Albert cams Como com os comandos echo ¢ printé do nivel do shell, o comando print do awk automa- ticamente fornece uma nova linha final, por outro Jado com 0 comando printé vor’ deve fornecé-lo, usando a seqiiéncia protegida \n. fe Esteja certo de separar os argumentos a imprimir com uma virgulat Sem a vit- 4S ag, Bilas awk concatena valores adjacentes: “08 § awe =F: +{ print "Usert $1 ‘is really" $5 }* etc/passwd Userrootie reallyroot Usertolstoyis reallyleo Tolstoy Usoraustenis reallyvane Austen Usercamsis reallyAlbert Cams ‘Uma coneatenagao dessa forma dificilmente 0 que voc® quer. Omitir a virgula umerro comum e dificil de encontrar. 3.3.4.5 Ages de iniciliragéo e limpeza Dois “padres” especiais, SECIN e END, permitem que vos fornega ages de inicializagao e de limpeza para seus programas awk. E mais comum usé-los em programas awk maiores, pois, eles sao geralmente escritos em arquivos separados em vez de em programas de uma linha: BEGIN { cddigo de inicializagéo } padriot ( acdot } padric2 ( agio2 } =D { e6digo de limpeza } Blocos 8BIN € BND siio opcionais. Se vocé os tem por convengio, mas néo obrigatoriamente, eles so colocados no infcio € no fim do programa awk, respectivamente, Voc também pode CAPITULO 3 * Pesquisando e Substitvindo 83 3.4 ter miitiplos blocos 3861N ¢ 8ND; awk os executa na ordem em que eles aparecem no programa: todos blocos 8861 uma vez no inicio, ¢ todos blocos sxD uma vez no final. Para programas. simples, ssom1 é usado para definir variéveis: § ave ‘BEGIN { FS = "2" 7 OFS = "HY } Use oBEGIN para defini varivels > { print $1, $5 }* /ete/passwa Um prograna proegido por aspas continua na segund linha root root tolstoy**iec Tolstoy Sola, como antes austen**Jane Austen canus**Albert Camas © padrio POSIX descreve a Linguagem avk € as opgdes para © programa aw. EBD 02uz POSH baseado no endo chamad “novo ase, primeiramenc langade para o mundo com o System V Release 3.1 em 1987, € um pouco modificado para 0 System V Release 4 em 1989. Infetizmente, mesmo hoje o /bin/awe do Solaris continua sendo a versio V7 original do awe de 1979! Em sistemas Solaris, voce deve usar /asr/xpg¢/bin/ ‘ark, ou insiaar uma das verses livres de avk mencionadas no Capitulo 9. RESUMO O programa grep ¢ a principal ferramenta para extrair linhas de interesse de um texto ou de arquivos de dados de entrada. POSIX sugere uma tinica verso com diferentes opgGes para fornecer 0 comportamento tradicionalmente obtido pelas variantes do orep: grep, egrep € forep. Embora voc possa pesquisar por strings constantes, expressdes regulares oferecem uma for- ma mais poderosa de descrever o texto a ser casado. A maioria dos caracteres casarn com eles, mesmos, porém alguns outros agem como metacaracteres, especificando agdes tais como “case zero ou mais de”, “case exatamente 10 de", e assim por diante. Expresses regulares POSIX vém em dois “sabores”: Expresses Regulares Bésicas (ERBs) © Expressdes Regulares Estendidas (EREs). Qual programa usa qual “sabor” de expresso regular € uma questio baseada na prética hist6rica, com a especificagao POSIX reduzindo o rngimero de “sabores” de expresséo regular a apenas dois. Na sua a maior parte, EREs so um super-conjunto das ERBs, mas nio completamente. Expressdes regulares so sensiveis ao locale em que o programa executa; em particular, fai- xas dentro de expressées em colchetes dever ser evitadas em favor de classes de caracteres, tal como [[:aLnua:]]. Muitos programas GNU tem metacaracteres adicionais, sed €4 principal ferramenta para se fazer substituigées simples de strings. Considerando que, segundo nossa experiencia, a maioria dos shell scripts usam sed apenas para substituigdes, propositalmente no cobrimos tudo que sed pode fazer. O livro sed & awk, referenciado no Capftulo 16, fornece mais informagoes. A regra do “mais longo e mais a esquerda” descreve onde o texto casa.e até onde 0 casamento se estende. Isso ¢ importante quando se faz substituigdes de texto com sed, awk, ou com um editor de textos interativo. Também ¢ importante entender quando hé uma distingao entre uma 84 __ Classic Shell Scripting linha ¢ uma string. Em algumas linguagens de programagio, uma simples string pode conter miitiplas linhas, nesse caso * ¢ $ geralmente se aplicam ao inicio ¢ fim de uma string. Para muitas operagoes, é util pensar em cada linha em um arquivo texto como um registro individual, com os dados da linha consistindo em campos. Campos sto separados por espagos ou um caractere delimitador especial, ¢ diferentes ferramentas Unix esto disponiveis para trabalhar com 0s dois tipos de dados. O comando cut corta faixas selecionadas de caracteres, ou campos ¢ 0 comando join € pritico para unir arquivos onde os registros compartilham um. campo chave comum. auk € seguidamente utilizado para programas simples de uma linha, em que é necessério apenas imprimir os campos selecionados, ou rearranjar a ordem dos campos em uma linha J que trata-se de uma linguagem de programagZo, vocé tem muito mais poder, flexibilidade e controle, mesmo em pequenos programas Pipelines Podem Fazer Coisas Impressionantes Neste capitulo, resolvemos tarefas relativamente simples de processamento de texto. O inte- ressante sobre todos os exemplos aqui € que eles sdo scripts construidos a partir de simples pipelines: cadeias de um comando ligado a outro, sendo cada um responsavel por uma im- portante tarefa, Quando voc® enfrenta um problema de processamento de textos no Unix, € importante man- ter em mente a filosofia de ferramentas Unix: pergunte a voc® mesmo como o problema pode ser quebrado em tarefas mais simples, pois para cada uma dessas tarefas jé existe uma ferramentae, se nfo, voc€ pode rapidamente fornecer uma com poucas linhas de programagaio shel! ou com uma linguagem script. 5.1 EXTRAINDO DADOS A PARTIR DE ARQUIVOS DE TEXTO ESTRUTURADOS A maioria dos arquivos administrativos do Unix sto arquivos simples em texto puro que vocé pode editar, imprimire ler sem precisar nenhuma ferramenta especial. Muitos deles residem no diret6rio padrao, /ete, Exemplos comuns s40 0s arquivos de senhas e grupos (pasewd & gxoup), a tabela de montagem do sistema de arquivos (fstab ou vEetab), 0 arquivo de hosts (hosts), 0 arquivo de inicializagao padrao do shell (profile), € 08 shell scripts de inicializagao e desligamento (shutdown), armazenados em uma érvore de diret6rios rc0.d, rc1.d, © assim por diante até rc6.< (pode haver outros diret6rios também). Formatos de arquivos so tradicionalmente documentados na Seco 5 do manual do Unix, portanto o comando man 5 passwd fomece informagdes sobre a estrutura do /etc/passwa.* Apesar do nome, 0 arquivo de senhas deve ter sempre permissio de leitura publica. Talvez, cle devesse ser chamado de arquivo de usuario, porque ele contém informagées bésicas sobre todas as contas de usuérios do sistema, agrupadas cm uma linha por conta, com campos sepa- + Em alguns sistemas, os formatos de arquivos esto na Segio 7; assim, voce pode precsar sar man 7 passve. 104 _ Classic Shel Sriting rados por dois-pontos. Descrevemos o formato de arquivo na Seco 3.3.1. Aqui estio algumas entradas tipicas: Jones:*:32713:899:Adrian W. Jones/080211/585-0123: /hone/jones: /bin/ksh dorothy: +:123:30:Dorothy Gale/KS321/S55-0044: /hone/dorothy: /bin/bash 1027:18: Toto Gale/1016322/555-0045: /hone/toto: /bin/tesh :#:302:10:Ben Franklin /0sD212/$55-0022: /hone/ben : /bin/bash 1457:57:John Hancock/S1G435/555-0099: /none/jhancock: /bin/bash 1110:20:Betsy Ross/BMD17/558-0033: /hone/bet sy: /bin/ksh tj:#:60:33:Thonas Jef Zerson/3¥D19/555-0095: /home/tj :/bin/bash george:* :692:42:George Washington/BS1999/555 -0001; /hone/george: /bin/tesh A titulo de revisdo, os sete campos de um arquivo de senbas sio: 1. nome de usuario; 2. senha criptografada, ou um indicador de que a senha esté armazenada em um arquivo sepa- rado; 3, mimero ID do usuario; 4, mimero ID do grupo; 5. nome pessoal do usudrio, ¢ possivelmente outros dados relevantes (Auimero do escritério, miimero de telefone, ¢ assim por diante); 6. diretério home; 7. shell de login. Todos menos um desses campos tém significado para varios programas Unix. O que nio tem € 0 quinto, que convencionalmente armazena informagdes de usuario que so relevamtes ape- has para humanos locais. Historicamente, ele foi chamado de campo gecos, por ter sido adi- cionado, nos anos 70, na Bell Labs, quando os sistemas Unix precisavam se comunicar com outros computadores que executavam o Sistema Operacional General Electric Comprehen- sive, e algumas informagGes extras sobre os usuarios Unix eram necessérias para aquele sis- tema. Atualmente, 2 maioria dos locais o usam apenas para registrar 0 nome pessoal, ento. simplesmente o chamamos de campo de nome. Para os propésitos deste exemplo, assumimos que o local registra informagGes extra no cam- po de nome: um identificador de prédio © um niimero de escritério (OSD211 na primeira entrada do exemplo), e um mimero de telefone (555-0123), separados co nome pessoal por barras. Uma coisa obviamente sitil que podemos fazer com esse arquivo € escrever algum software para criar um diret6rio de dados de escrit6rio, Dessa forma, apenas um tinico arquivo, /etc/ pasewd, precisa ser mantido atualizado, ¢ arquivos derivados podem ser criados quando o ar- quivo principal for modificado, ou de forma mais sensfvel, através de uma tarefa do cron, que cexecuta em intervalos compativeis (discutiremos 0 cxon na Secdo 13.6.4). Para nosso primeiro experimento, fizemos 0 diret6rio de dados de escritério em um simples arquivo texto, com entradas como esta: Franklin, Ben s0sp2126555-0022 Gale, Dorothy (e10153216555-0064 O « representa um caractere ASCII fab. Colocamos 0 nome pessoal em uma ordem conven- cional de diretério de dados (sobrenome primeiro), completando 0 campo de nome com espa- CAPITULO 5 Pipelines Podem Fazer Coisos Impressionantes 105, 0s para uma largura fixa conveniente. Prefixamos 0 nimero do escritério ¢ do telefone com caracteres tab para preservar uma estrutura iti] que outras ferramentas podem explorar. Linguagens script, tais como 0 awk, foram projetadas para tornar tais tarefas féceis, fornecen- do processamento de entrada automatizado e separagdio de registros de entrada em campos, de forma que podemos escrever uma tarefa de conversdo completa em uma dessaslinguagens. Porém, queremos mostrar como chegar ao mesmo resultado com outras ferramentas Unix. Para cada linha do arquivo de senhas, precisaremos extrair 0 campo cinco, separé-lo em trés subcampos, rearranjar os nomes no primeiro subcampo, ¢ entdo escrever uma linha de direté- rio de dados de escritério para um processo de ordenamento, ank © cut so boas ferramentas para extragdo de dados separados por campo ‘{ print $5 }' |... “£5 |. Existe uma ligeira complicagdo no fato de termos duas tarefas de processamento de campos que, para simplificar, queremos manter, separadas, mas precisamos combinar suas safdas para fazer a entrada do diret6rio de dados. © comando join é exatamente o que precisamos: ele espera dois arquivos de entrada, cada um ordenado por uma chave dinica comum, e une linhas compartithando a mesma chave em uma tnica linha de safda, com controle do usutio sobre 0s campos que iro para a saida, J4 que nossas entradas de diretério de dados contém trés campos, para usar 0 join preci- saremos criar trés arquivos intermediérios contendo os pares separados por dois-pontos, chave:pessoa, chave:escritério ¢ chave-telefone, um para cada linha. Eles podem todos ser arquivos temporérios, jé que séo derivados automaticamente do arquivo de senhas. Que chave usaremos? Bla precisa apenas ser tnica, entio pode ser o ntmero do registro no arquivo original de senhas. Nesse caso, também pode ser 0 nome de usuario, j4 que sabemos que eles so Unicos no arquivo de senhas, além de fazerem mais sentido para humanos do que os ntimeros constumam fazer. Depois, se decidirmos ampliar nosso diretério de dados com informagées adicionais, como o cargo de trabalho, podemos eriar um outro arquivo néo tempordrio com o par chave:cargo ¢ adicioné-lo aos estigios de processamento. Ao invés de colocar diretamente os nomes dos arquivos de entrada e safda em nosso progra- ma, é mais flexfvel escrever o programa como um filtro, para que ele leia a entrada padrdo e escreva na safda padrao, Para comandos que raramente so usados, é aconselhvel dar a eles, rnomes descritivos, em vez de nomes curtos e criptogréficos, ento comecamos nosso progra- ‘ma shell desta forma: #1 bin/sh # Filter an input strean formatted Like /etc/passwd, # and cutput an office directory derived tron that data ‘ 4 Usage: # pasewd-to-directory < /etc/pasowd > office-directory-file # ypeat passvd | passud-to-directory » office-directory-file ‘ niscat passwi.org dir | passwi-to-directory > ofiice-directory-file J4 que o arquivo de senhas tem permissio de leitura publica, qualquer dado derivado dele também é pablico, entiio no hé real necessidade de restringir 0 acesso aos nossos arquivos intermedisrios do programa. Porém, porque todos nés as vezes temos que lidar com dados sigilosos, é bom desenvolver o habito de programagao de permitir o acesso a arquivos apenas 106 _ Classic Shel Sriting para aqueles usuérios ou processos que precisam dele, Nés enti redefinimos 0 unask (veja Se¢ao B.6.1.3 no Apéndice B) como a primeira acd em nosso programa: umask 077 Restringe 0 acexso aqpenas nésco arquivo temporiio Para contabilidade ¢ depuragio. € titi] ter alguma caracteristica em comum nos nomes de arquivos temporérios e, para evitar a desordem no diret6rio corrente com eles, 05 nomeamos, com 0 prefixo /tmp/pd. . Também precisamos que 0s nomes sejam tinicos para evitar colisdes, de nomes quando méltiplas instancias de nosso programa esto executando ao mesmo tempo: 0 ntimero do processo, disponfvel na varivel $$ do shell, € um sufixo distinto (0 uso de $$ € descrito em mais detalhes no Capftulo 10.). Entio definimos essas varidveis do shel! para representar nossos arquivos temporarios: PERSON=/tmp/p4. key person. $$ Nomes de arguivos temporirio inicos OFFICE=/tmp/pd. key office. $$ TELEPHONE=/tmp/pa.key. telephone. $$ USER=/tnp/pd key. user. $$ Quando a tarefa termina, seja normalmente ou anormalmente, queremos que os arquivos tempordrios sejam apagados, ento usamos 0 comando trap: trap "exit 1" HUD INT PIPE QUIT TERM trap "xm -£ §PERSON SOFFICE $TELEPHONE SUSER" EXIT Durante o desenvolvimento, simplesmente podemos comentar o segundo tap, preservando 08 arquivos temporarios para uma subseqiiente avaliagio. (0 comando trap € descrito na Seco 13.3.2. Por ora, € suficiente entender que quando o script encerra, 0 comando trap arranja as coisas para que 0 rn com os argumentos dados seja automaticamente executado.) Precisamos dos campos um ¢ cinco repetidamente, ¢ uma vez os tendo, no os requisitamos novamente do stream de entrada, eno comecamos por extraf-los em um arquivo temporirio: awk -P: '( print $1°:* 95} > SOBER La entrada prio Fizemos o par chave:pessoa primeiro, com um programa sed de dois passos seguido de um simples ordenamento de linhas; 0 comando sort € discutido em detalhes na Seco 4.1 ged -e 'e=/.4= =! \ ce MeV DEVAN VCE 1) Osscript usa = como 0 caractere separador para o comando s do sed, j4 que tanto barras como dois-pontos aparecem nos dados. A primeira edigdo remove tudo a partir da primeira barra até o fim da linha, reduzindo a linha desta forma: 3, \2=! <$USER | sort >$PERSON jones:Adrian W. Jones /0s0211/555-0123 inka de entrada transformando nisto: jones:Adrian W. Jones Resultado da primeira ego A segunda edico € um pouco mais complexa, pois casa trés subpadrtes no registro. A pri- meira parte, *\([*r]*\, casa 0 campo de nome de usuério (por exemplo, jones). A segunda parte, \(.*\)0 casa com o texto até espago (por exemplo, AdriarcW.0; o O significa um caractere de espaco). A tiltima parte, \([°0]*\), casa com o texto que nao é espaco rema- nescente no registro (por exemplo, Jones). A substituigio de texto reordena os casamentos, produzindo algo como Jones, TAdrien W. O resultado desse comando sed 6 0 reordenamento desejado: jones:dones, Adrian W Resultado da segunda edigio CAPITULO 5 * Pipelines Podem Fazer Coisos Impressionantes 107 A seguir, fazemos 0 arquivo do par chave:escritério: VUE OAVUNIEL sed -e ' 1:\25" < $usER | sort > SoFFICE O resultado ¢ uma lista de usustios e escrit6rios: jones:0sp211 A criagio do arquivo de pares chave:telefone é semelhante: apenas precisamos ajustar 0 pa- dro de casamento: sed -e ta=*\(I* NU Nesse estégio, temos trés arquivos separadose cada um esté ordenado. Cada arquivo consiste da chave (0 nome de usuério), de um dois-pontos, e dos dados pessoais (nome completo, crit6rios, ntimero de telefone). © contetido do arquivo $e#RSON parece com isto: M/MIN) *\2:\2e" < GUSER | sort > TELEPHONE ben: Franklin, Ben betsy:Ross, Betsy O arquivo so7F1cz contém nomes de usuarios e dados do escritério: ben:080212 bet sy:ENDL7 O arquivo $7SLEPHONE registra os nomes de usudrios ¢ os ntimeros de telefone: ben:555-0022 betsy:555-0033 Por padrio, o comportamento padrio do join imprime a chave comum, ¢ ento os campos, remanescentes da linha do primeiro arquivo, seguidos dos campos remanescentes da linha do segundo arquivo. A chave comum fem como padrio ser 0 primeiro campo, mas isso pode ser modifiado por uma opgio de linha de comando; no entanto, no precisamos desse recurso aqui. Normalmente, espagos separam campos do join, mas com a opgo -t podemos mudar © separador: no caso, usamos essa opco como - As operagdes do joia so feitas em um pipeline de cinco estdgios, conforme a seguir: 1. Combina as informagdes pessoais ¢ a localizagao do escritério: join -t+ $PERSOM SORFICE | Os resultados dessa operagio, que se tornam entrada para o proximo estégic com isto: ben: Franklin, Ben:OSD212 betsy:Koss, Betsy:EMD17 2. Adiciona o mémero de telefone: + STRLEPHONE | ... | join - Os resultados dessa operagdo, que se tornam a entrada para o proximo estégio, parccem, com isto: ben:Franklin, Ben:0Sb212:555-0022 betsy:Ross, Bet sy:BND17:555-0033 108 _ Classic Shel Sriting 3. Remove a chave (que é 0 primeiro campo), jé que ela nao é mais necesséria. Isso é mais. facilmente feito com o cut ¢ uma faixa que diz. “use os campos dois até o final”, desta forma: | out -a: -£2- |... Os resultados dessa operagZo, que se tornam entrada para o pr6ximo estigio, se parecem com isto: Franklin, Ben:08D212:555-0022 Ross, Betey:BMD17:555-0033 4, Reordenar os dados. Os dados foram previamente ordenados pelo nome de usuétio, mas. agora eles precisam ser ordenadios pelo sobrenome. Isso € feito com o sore: ceo | sort te “1,2 -k2,2 43,3 | Esse comando usa um dois-pontos para separar arquivos, ordenando pelos campos 1, 2€ 3, em ordem., Os resultados dessa operagio se tornam a entrada para 0 proximo estdgio, se parecendo com: Franklin, Ben:08D212:555-0022 Gele, Dorothy :#S321:555-0044 5. Por fim, a safda é reformatada usando-se 0 comando print do awk para separar cada campo com caracteres tab. © comando paraisso é: | awk =F: { print£("#-39s\tte\tts\nt, $1, $2, $3) }* Por questdes de flexibilidade ¢ facilidade de manutencao, a formatagio deve sempre ser deixada para o final. Até aquele ponto, tudo 0 que temos so apenas strings de tamanho arbitrério. Aqui temos o pipeline completo: join -ts $PERSON SOFPICE | join -t: = STELEPHONE | cut -d: -f 2- | sort -t: -kL,1 -k2,2 -%3,3 | awk -F: '{ printé("$-39e\tte\tta\n", $1, §2, $3) J! O comando printf do avk usado aqui € téo semelhante ao comando printf do shell que seu significado deve estar claro: imprimir o primeiro campo separado por dois-pontos ajustado & esquerda em um campo de 39 caracteres, seguido por um tab, o Segundo campo, outro tab, € 0 terceiro campo. Aqui esto os resultados completos: Franklin,Ben 0sp2126855-0022 cale,Dorothy enqys3.210555-0046 Gale, Toto 1910183220555-0045 Eancock, John 1#981G4350555-0099 Jeffereon, Thomas ‘#EMD196555 -0095 Jones, Adrian W sosp2i1es5s-0123 Ross, Betsy 95NDL70585-0033 Washington, George 19B979990555-0001 Isso € tudo 0 que se precisa para o trabalho! Nosso script completo tem pouco mais de 20 linhas, excluindo os comentarios, com cinco passos principais de processamento, Agrupamos, tudo em um s6 lugar no Exemplo 5-1. Exemplo 5-1 Criando um diret6rio de dados de escritério #1 /bin/sh # Filtra um strean de entrada fornatado, cono o /eto/pasewd, CAPITULO 5 * Pipelines Podem Fazer Coisos Impressionantes 109 Exemplo 5-1 Criando um diret6rio de dados de escritbrio (continuagao) 4 @ inprine un Giretorio de dados de escritorio derivado destes dados. ‘ 4 Uso: 4 —pasewd-to-directory < /etc/passd > office-directory-file 4 ——_ypcat pasovd | passnd-to-directory > office-directory-file # ——niscat passvd.crg_dir | pasewd-to-directory > office-directory-iile unaek 07 PERSON=/tmp/pd-key.person.$$ OFPICE~/tmp/pd.key. office. $$ TELEPHONE~ /tup/pd. key. telephone. $$ USER=/tmp/pd.key user .$$ trap texit 1" HUP INT PIPE QUIT TERM trap trm -f SPERSON SOFFICS $TELSPHONE SUSER" EXIT awk -P: '{ print $1 ":" $5 }' > SUSER sed -e 'oe/.te =! \ AACA VCS T#\=\18\3, \2e! < $USBR | sot > SPERSOR A\EC/IA/\LC/IA\I(.8$-\be\z0! < $usER | sore > SorsicE CTD A/A/E/A/\(O71A\)\1:\25" < $USER | sort > STELBPHONE join -t: $PERSON SOFFICE | join -t: - STBLEPAONE | cut -4: -£ 2- | sort -t: -KL,2 -K2,2 -13,3 | ave -F: '( prince ("-395\tes\tas\n", $1, §2, $3) } O real poder da programagao shell script se mostra quando queremos modificar o script para fazer um trabalho ligeiramente diferente, tal como a insergdo de um cargo a partir de um ar- quivo chave:cargo mantido em separado. Tudo o que temos que fazer ¢ modificar 0 pipeline final para parecer com algo assim: join -t: $PERsoN /etc/passwd. job-title | join extracom o cargo join -t: = $OFFICE | join -t: - STELBPHONE | cut -d: -£ 2- | sort -t: -kL2 -K3,3 -k4,4 | Modifar ocomando sort fave -F: '{ printt(*-398\t4-236\tea\tes\n", $1, $2, $3, $4) }* Eo comando de jormatagao custo total para o campo extra do diretério de dados ¢ o acréscimo de mais um join, uma mu- danga nos campos de ordenagiio, e uma pequena alteragdo no comando awk de formatagao final. Por sermos cuidadosos em preservar os delimitadores de campo especiais em nossa saida, podemos, de forma trivial, preparar diret6rios de dados alternativos desta forma: passud-to-dixectory < /ete/passud | sort -t' passwd-to-directory < etc/passwd | sort -t'e! -k2,2 » dir.by-office -k3,3 > dir.by-telephone Como de costume, + representa um caractere tab ASCII. Uma premissa critica de nosso programa & que existe uma chave tinica para cada registro de dados. Com ess chave iinica, visGes separacas dos dados podem ser mantidas em arquivos com os pares chave:valor. Aqui, a chave foi um nome de usuario Unix, mas em contextos maiores, poderia ser um némero de livro (ISBN), nimero de cartdo de crédito, nimero do 110 _ Classic Shell Scripting 5.2 Uma digresséo sobre bancos de dados A maioria dos bancos de dados comerciais sio hoje construidos como bancos de da- dos relacionais: 0 dado € acessfvel como pares chave-valor, ¢ as operagées de jungao so usadas para construir tabelas com varias colunas para se obter visdes de subcon- juntos selecionados de dados. Bancos de dados relacionais foram. propostos pela pri- ‘meira vez em 1970 por B. F Codd’, que os promoveu ativamente apesar da oposigao inicial da indstria, que argumentava que eles nao poderiam ser implementados de forma cficiente. Felizmente, programadores espertos logo descobriram como resol- ‘yer o problema de eficiéncia. O trabalho de Codd ¢ tio importante que, em 1981, ele recebeu o prestigiado ACM Turing Award, a coisa mais proxima do Prémio Nobel da ciéncia da computagzo. Atualmente, existem muitos padrdes ISO para a Structured Query Language (SQL), ‘que tornam 0 acesso a bancos de dados independente de fabricante, e uma das opera- ‘ges mais importantes do SQL ¢ o join. Centenas de livros foram publicados sobre ‘SQL; para aprender mais, pegue um livro mais geral como SQL in a Nutshell.” Nossa simples tareta de diret6rio de dados de escrit6rio contém, uma importante ligdo sobre ‘© conceito central dos bancos de dados relacionais modernos, ¢ as ferramentas de software do Unix podem ser de grande valor na preparagao de entrada para bancos de dados e no processamento de sua saida. “EF Co Att ase a ag Str Dts ks Crs KH, 130637987, ht (1570, at as: A ecal ean fr Pod, Cnn KG, 2512) 1017, Fria (982) Pabea eu a) "aren Kin Dai i, Oe & sues, 00, EN 1565927443. Wo nb itx/ Aw natutheky/>te ti sokshin pa a cel dis dS. funcionério, niimero nacional do sistema de aposentadoria, niimero da pega, ntimero de es- tudante, e assim por diante. Agora sabemos porque temos tantos mimeros associados 2 nds! Vocé também pode ver que esses operadores nao precisam ser niimeros: eles podem ser ape- nas strings de texto tinicas.. DADOS ESTRUTURADOS PARA A WEB A grande popularidade da World Wide Web faz com que seja desejavel estar apto a apresentar dados, como 0 diret6rio de dados de escritério desenvolvido na tltima sega, em uma forma lum pouco mais apresentével que o nosso simples arquivo texto. Arquivos da web sio principalmente escritos em uma linguagem de marcagao de textos cha- mada HyperText Markup Language (HTML). Ela én, na verdade, uma familia de linguagens, que sao instancias especfficas da Standard Generalized Markup Language (SGML), definida em muitos padrées ISO desde 1986. O manuscrito deste livro foi escrito em DocBook/XML, que € também uma instancia especffica de SOML. Vocé pode encontrar uma descrigao com- pleta de HTML em HTML & XHTML: The Definitive Guide (O’Reilly).* Para os propGsitos desta seco, precisamos de apenas um subconjunto de HTML, que apre- sentamos aqui em um pequeno tutorial. Se voc® jé esté familiarizado com HTML, apenas, pule uma ou duas paginas, Eis aqui um arquivo minimo compativel com o padréio HTML produzido por uma ferramenta Stil escrita por um de nés:** *® Adicionaimente a esse live (listado na Bibliografia), centenas de livros sobre SGML e derivads so istados em htp:/Arvn ‘ath.siah.edufpubiex/bib’sgmt iu ¢ hup:/>wwn math.wah.edu/pubterbibsgi2000.hunt. ** Dispontvel em hup://wiew.math.wiah.edu/pub/sgn. CAPITULO 5 * Pipelines Podem Fazer Coisos Impressionantes 111 § echo Hello, world. | htnl-pretty ent Prettyprinted by html-pretty flex version 1.01 [25-Aug-2001] on Wed Jan 8 12:12:42 2003 --> for Adrian W. Jones (Joneséexample.con) --> KIM Please supply a descriptive title here --> Os pontos a serem observados nessa safda HTML sio: © comentarios em HTML sfo envolvidos por ; '* comandos especiais de processamento sio envolvidos por aqui, o comando Doc ‘Ty? indica a um interpretador SGML que tipo de documento € esse ¢ onde achar 0 arquivo da gramética: ‘* amareagdo € fornecida por palavras envolvidas por parénteses angulares, chamadas tags. Em HTML, 0 caso das letras ndo € significativo nos nomes das tags: html normalmente usa letras em maitisculo nas rags por questoes de legibilidade; ‘+ ambientes de marcago consistem de uma fag de comego, , € uma fag de fecha- mento, , € para muitas tags, ambientes podem ser aninhados uns com os outros de acordo com regras definidas nas graméticas do HTML; ‘* um documento HTML ¢ estruturado como um objeto HTML contendo um objeto HEAD e ‘um objeto BoDy; '* dentro do Kean, um objeto rrrLe define o titulo do documento que o navegador web iré exibir na barra de titulo da janela ¢ em listas de bookmarks. Além disso, dentro do KEAD, © objeto rank geralmente cartega informagées sobre o mantenedor da pégina web; ‘+ a parte visfvel do documento que o navegador web mostra ¢ 0 contetido do objeto BODY; ‘* espagos em branco nio sto significativos fora de strings protegidas, portanto podemos usar livremente espagos horizontais e verticais para enfatizar a estrutura, como um for- mator para impressio de c6digo HTML faz; '* todo o resto € apenas caracteres texto ASCII imprimiveis, com trés excegdes. Parénteses angulares literais precisam ser representados por codificagdes especiais, chamadas enti- dades, que consistem de um “e comercial” (&), um identificador, e um ponto-e-virgul Et; © sgt. Jaque 0 “e comercial” inicia uma entidade, cle tem seu préprio nome literal de entidade: sanp;. HTML suporta um repert6rio modesto de entidades para caracteres acentuados, que cobre a maioria das linguagens do Oeste Europeu para que possamos escrever, por exemplo, cafseacute; du bon gowcire;t para ter café du bon got; 112 _ Classic Shell Scripting ‘+ apesar de nio termos mostrado cm nosso exemplo, mudangas nos estilo das fontes séo possiveis em HTML com os ambientes 8 (negrito), 54 (énfaze), 2 (itélico), STRONG (negri- toextra), e77 (ypewriter —caracteres com largura fixa); escreva <> Jones, Adrian W. 555-0123, oso211 Uma codificagio equivalente, porém mais compacta e dificil de ler, poderia ser feita assim TABLES <7D>555-0123«/TD>eTD>08021 Por termos escolhido preservar os separadores de campo especiais nas verses texto do di- retério de dados de escrit6rio, temos informagées suficientes para identificar as células em cada linha. Além disso, devido aos espacos em branco no serem significativos em arquivos, HTML (exceto para humanos), nfo precisamos ser muito cuidadosos com o alinhamento das tags: se isso for necessério mais adiante, nem -pretty pode perfeitamente fazer esse trabalho, Nosso filtro de conversao tem enti trés passos: 1. Imprime o padrao de texto do cabegalho até 0 inicio do corpo do documento. 2. Transforma cada linha do diretério de dados em uma marca de tabela. CAPITULO 5 * Pipelines Podem Fazer Coisas Impressionantes 113 3. Emite o padrio de texto final. ‘Temos que fazer uma pequena mudanga a partir de nosso exemplo mfnimo: 0 comando bocryee tem que ser atualizado para um nivel de gramética mais atual, de forma que ele parega com: Voce no precisa memorizar isso: tmi-pretty tem opgdes para produzir safda em qualquer tum dos nfveis de gramética padrao HTML, portanto voce precisa apenas copiar dessa safda tum DocryPz compativel. A maior parte do trabalho € apenas escrever 0 c6digo padrdo para o cabecalho para o fecha- mento do arquivo, o que ¢ bastante simples, pois basta copiar o texto do exemplo minimo de HTML. 0 tinico passo em que ¢ necessério programago € o do meio, e isso pode ser feit com apenas um par de linhas em awk. Pode-se ter ainda menos trabalho usando uma substi tuigo do editor de streams sed com dois comandos: um para substituir os delimitadores tab embutidos por e um outro @ seguir para incorporar toda a linha em <7RseTD>. .. arquive_saida cat << BOPILE Padréo de c6tig de cabecalho boilerplate Office directory BOPILE sed -e ‘'ee&=\samp;-g' \ Convertecaracieres especias para entdades se tee &=" cat << SOFILE Padrdo de cbtigo de fectamento de arquivo
SOPILE 114 _ Classic Shell Scripting A notagdo << € chamada de documento aqui. Bla é explicada com mais detalhes na Segao 7.3.1. Resumidamente, o shell 18 todas linhas até o delimitador que segue c< (sorts nesse caso), faz substituiga0 de variveis ¢ de comandos nas linhas delimitadas ¢ alimenta 0 resul- tado para a entrada padréo do comando, H4 um ponto importante sobre o script do Exemplo 5-2: ele é independente do niimero de colunas da tabela! Isso significa que ele pode ser usado para converter para HTML qualquer arquivo de dados separados por tabs . Programas de planilhas de célculo podem, geralmente, salvar dados em tal formato de maneira que nossa simples ferramenta produza o HTML cor- reto a partir dos dados. Fomos cuidadosos no tsv-to-hem para manter a estrutura de espagos do diretGrio de dados de escritério oficial, porque isso torna mais fécil a aplicagzo de filtros mais adiante no stream. Ontml-pretey foi, de fato, escrito precisamente por esta razao: a padronizago do layout de marcagio HTML simplifica radicalmente outras ferramentas HTML. Como podemos tratar a conversio de caracteres acentuados para entidades HTML? Pode- ‘mos aumentar 0 comando sed com pasos extra de edigo como -e * mas existem em tomo de 100 ou mais entidades para serem tratadas ¢ provavelmente vamos pre- cisar de substituigdes semelhantes conforme convertemos outros tipos de arquivos texto para HTML. Em vista disso, faz sentido delegar essa tarefa a um programa em separado que podemos reusar, tal como 0 estigio de pipeline seguindo o comando sed do Exemplo 5.2, ou 0 filtro aplicado depois (esse € 0 prinespio “de evitar a construgdo de ferramentas especializadas” em agdo). Tal programa é apenas uma tediosa tabulago de comandos de substituigdo e precis ‘mos de um para cada codificagao local de texto, tais como as virias ISO-8859-n péginas men- cionadas na seco B.2 no Apéndice B. Esse filtro ndo € mostrado completamente aqui, mas uum fragmento de um no Exemplo 5.3 oferece uma nogdo geral. Para leitores que precisarem dele, inclufmos programa completo para tratamento do caso comum de caracteres do Oes- te Europeu na codificacdo ISO 8859-1 nos programas cxemplo deste livro. O repertério de entidades HTML nao ¢ suficiente para outros caracteres acentuados, mas desde que a World Wide Web esté se movendo na dirego do Unicode « XML no lugar de ASCII ¢ HTML, esse problema est senco resolvido de outra forma, pela eliminagao das Timitagdes dos conjuntos de caracteres. Exemplo 5-3 Trecho do programa iso8859-I-to-himl 41 /bin/sh 4 Converte uma stream de entrada contendo caracteres na codificacac 1808859-1 4 da faixa 128..255 para equivalentes HIML em ASCII. # Characteres 0..127 sao preservados normalmente coro ASCII. 4 4 Uso: 4 is08859-1-to-html arguivo(s) entrada > arquivo_saida sed \ CAPITULO 5 * Pipelines Podem Fazer Coisas Impressionantes 115, 5.3 Exemplo 5-3 Trecho do programa iso8859-1-t0-himal (continuagdo) 2 tga" Aqui esté um simples exemplo desse filtro: yum j=g' \ § cat danish Exibe un exemplo de texto em dinamarqués usando cacouticugdo ISO 8659-1 @en med den 18 i le af én helvo, og én stor @, lengs den graske kyst § 4808859-1-to-html danish Converteo texto para entidades HTML @en med den 14 i 14 af én halvo, og én ctor 9, lange den gracke kyst TRAPACEANDO EM PALAVRAS CRUZADAS Palavras cruzadas diio pistas sobre as palavras, mas a maioria de nés fica preso quando nao. consegue pensar em, digamos, uma palavra com dez letras que comeca com um b e tem ou. tum x ou um z na sétima posicao. Casamento de padrées usando expressdes regulares com 0 awk ou grep claramente vem & tona, mas que arquivos devemos procurar? Uma boa escolha € 0 dicionério ortogréfico do Unix, disponivel como /usr/dict /vozds em muitos sistemas (outras populares localizagtes para esse arquivo so /usr/share/dict/words ¢ /usr/share/1ib/aict /worés..) Este é um simples arquivo texto, com uma palavra por linha, ordenada de forma lexicogréfica. Podemos, facilmente criar outros arquivos de aparéncia similar a partir de qualquer colegio de arquivos texto, desta forma: cat file(s) | tr aza-z | tr -ca-z\! ‘\n' | sort -u O segundo estégio do pipeline converte maitisculas em mindsculas, 0 terceiro substitui o que nfo for letra por caracteres de nova linha, ¢ o iltimo ordena o resultado, mantendo apenas as linhas tnicas. O terceiro estégio trata apéstrofes como letras, j& que elas so usadas em con- tragdes. Todo sistema Unix tem colegées de texto que podem ser minadas dessa forma~ por exemplo, as pégina de manual formatadas em /usr/nan/cat*/* € /usr/local/man/cat*/*. Em um de nossos sistemas, eles forneceram mais de 1 mithao de linhas de prosae produziram uma lista de mais ou menos 44.000 palavras tinicas. Existem também listas de palavras para diizias de Vinguas em vérios arquivos na Internet." ‘Vamos assumir que construimos uma colecdo de listas de palavras dessa forma e as armaze- amos em um local padrao que possamos referenciar a partir de um script. Podemos entao escrever 0 programa apresentado no Exemplo 5-4 Exemplo 5-4 Auxiliar de solugdes de palavras cruzadas Ht /bin/sh 4 Casa um padrao como egrep(1) contra uma colecao de # Listas de palavras 8 4 Uso: 4 puzzle-help padrao-esrep [arquivoe-lista-de-palavraa] Disponiveis em jip:/ip.0x.ac uk/pubswordiistt,tp-/fgiclab.scn.rain.com/pub/wordlisis, fp: /biblio.org/pubsdecibooks! _gutenbergletex®5fpgw* ¢ htp:/ovrwiphreakorg/uiniAnonilistssml, Uma basca por “word list” em qualquer ferramenta Ge pesquisa da Interetretomna muitas mais. 116 _ Classic Shell Scripting 5.4 Exemplo 5-4 Auiiliar de solugdes de palavras cruzadas (continuagao) FILES=" Jusr/Aict/woras fast/share/dict /words Jusr/share/1ib/dict/words /asr/ Local /shaxe /dict /words biology Jusr/ local /share/dict /words.chenistry Jusr/Loval/share /dict /words.general fusr/Local/share/dict /words.kmuth /asr/Local/share/dict/words latin fusr/ Local /share /dict /words .manpace: fasr/ Local /share/dict /words nathenatics Jusr/Local/share/dict /words.physics Jusx/Local/share /dict /words.roget fusr/Local/share/dict/words.sciences fasr/ Local /share /dict /words .unix fusr/Local/share /dict /words.vebster pattern="$1" egrep -h -i "Spattem" SPILES 2> /éev/null | sort -u -t A varivel PruEs armazena a lista interna de arquivos de lista de palavras personalizada para 0 ambiente local. A opeao - do grep suprime os nomes de arquivos da saida, a pedo ~i ignora a diferenga entre maitisculas/mindsculas e descartamos a safda padrdo de erro com 2> /dev/ 1nu1, no easo de algum arquivo de lista de palavras no existir ou de eles nio terem permissao de leitura (esse tipo de redirecionamento € descrito em “Manipulagio de Descritor de Arqui- vos” [7.3.2]). O estégio final, sort, reduz.o relatério para apenas uma lista tinica de palavras, ignorando maidsculas/minésculas. Agora podemos encontrar a palavra que estamos procurando: $ puszle-help '“b.....(xe]...8* | fmt bamboozled Banboozler banhoozles baDenizens bdWheezing Belehazzar botanizing Brontozoun Bucholzite bulldozing Voc consegue pensar em uma palavra em inglés com seis consoantes em uma linha? Aqui estd uma ajuda: § purzie-holp ‘ {‘aciouyl {6)' /usr/aict/vords Knightsbridge ighta't oughtn't Se voc# nao conta “y” como uma vogal, muitas mais aparecem: encryption, klystron, por- phyry, syeygy, e assimn por diante. Poderiamos rapidamente excluir as contragées da lista de palavras usando um filtro no pas- so final — egrep -i '*[a-z]+3" — mas hd pouco problema em manté-las na lista de palavras. LISTAS DE PALAVRAS De 1983 a 1987, 0 pesquisador Jon Bentley da Bell Labs escreveu uma coluna interessante ‘na Communications of the ACM imtitulada Programming Pearls. Alguns desses artigos foram mais tarde reunidos, com modificagdes substanciais, em dois livros listados no Capftulo 16. CAPITULO 5 * Pipelines Podem Fazer Coisos Impressionantes 117 Em deles, Bentley langou este desafio: eserever um programa para processar um arquivo texto e dar como safda uma lista das n palavras mais freqtientes, com as contagens de sua freqiiéncia de ocorréncia ordenadas por ordem decrescente. Os notéveis cientistas da com- putago, Donald Knuth David Hanson respondcram individualmente com solugdes interes- santes ¢ inteligentes em programas* que cada um deles levou muitas horas para escrever. A especificagio original de Bentley era imprecisa, ent3o Hanson as reorganizou desta forma: dado um arquivo texto € um inteiro n, voce deve imprimir as palavras (e suas freqiiéneias de ocorténcia) cujas freqlléncias de ocorréncia esto entre as.n maiores em ordem decrescente de frequéncia. No primeiro dos artigos de Bentley, um colega pesquisador da Bell Labs, Doug Mellroy, revisou o programa de Knuth ¢ ofereceu uma soluedo Unix em seis passos que levou apenas alguns minutos para ser desenvolvida ¢ funcionou corretamente j4 na primeira vez. Ainda ais, diferentemente dos dois outros programas, o de Mcliroy era livre de constantes mégicas explicitas que limitavam os tamanhos das palavras, 0 nimero de palavras tinicas,¢ o tamanho do arquivo de entrada. Tamhém, a nogio de o que constitui uma palavra é definida inteira- ‘mente por simples padres dados em seus dois primeiros comandos executéveis, tornando ficeis as modificagées no algoritmo de reconhecimento de palavras. O programa de Meliroy ilustra o poder da abordagem das ferramentas Unix: quebrar um pro- blema complexo em partes simples que vocé j sabe como tratar. Para resolver o problema da freqiiéncia de palavras, McIlroy converteu arquivo texto em uma lista de palavras, uma por linha (tx fez 0 trabalho), mapeou palavras para um nico caso (maidisculas ou minésculas, tr novamente), ordenou a lista (sort), a reduziu para uma lista de palavras tinicas com con- tagens (unig), ordenou aquela lista em ordem descendente pela contagem (sort) e, por fim, imprimiu muitas das primeiras entradas na lista (sed, apesar de 0 head funcionar também). programa resultante mereceu receber um nome («f, de word frequency, ou seja, frequéncia de palavras) e ser colocado em um shell script com um eabecalho de comentario. Também estendemos 0 comando sed original de McIlroy para tomar opcional o argumento que regula © tamanho da safda e modemizamos as opgbes do sort. Mostramos 0 programa completo no Exemplo 5-5. Exemplo 5-5 Filtro de freqliéncia de palavras #1 /bin/ek 4 Le un stream de texto da entrada padrao © imprine na saida # padrao una Lista dae n (por oniseao: 25) nais frequentes # palavras que ocorreran e suas contagens de frequencia, om # orden decrescente de contagen. 4 # Uso: 4 ve [nl] te -es A-de-z\" "\n! | Subst ndorletras por earacteres de nova tha trazas | Transforma naitscuas em miniscule sort | Ordena as pelavras em ordem erescente unig -c | Elmina duplicatas, mosirand suas contagens Programming Pearis: A Literate Program: & WEB program for commen words, Comm. ACM 29(6),471-483, Junho (1986), ‘¢ Programming Pearl: Literate Programming: Printing Common Words, 30), 584-599, July (1987). O artigo de Knuth foi reimpresso no seu livro Literate Programming, Stanford University Center forthe Study of Language and Information, 1992, ISBN 0-937073-80-6 (papel) and 0-937073-81-4 (ecido) 118 _ Classic Shell Scripting Exemplo 5-5 Filtro de freqiténcia de palavras (continuagéo) sort -KL,anr -ka | Ondenade forma decrescente pela comtagem = 5' | we -1 “0 Esse € mais ou menos o nimero de palavras que se pode esperar que um estudante aprenda em um curso de um semestre de uma lingua estrangeira, ou que uma crianga aprenda antes de entrar na escola. Shakespeare ndo tinha computadores para ajudar a analisar seu texto*, mas podemos especu- lar que parte de sua genialidade estava em fazer a maior parte do que escreveu compreensivel para a mais ampla audiéncia possivel no seu tempo. Quando aplicamos w? a textos individuais das pecas de Shakespeare, encontramos que Ham- let tem 0 vocabulério mais amplo (4548), enquanto que “Comedy of Erros” tem o menor (2443). O niimero total de palavras tnicas no compo das pegas e sonetos de Shakespeare é de aproximadamente 23.700, o que mostra que vocé precisa de exposigdo a muitas pecas para aproveitar a riqueza de seu trabalho. Em tomo de 36 porcento dessas palavras so usadas, apenas uma vez, e apenas uma palavra comega com x: Xantippe, em “Taming of the Shrew”. Claramente, hé bastante material em Shakespeare para os entusiastas de palavras cruzadas e analistas de vocabuldrios! 5.5 LISTAS DE TAGS uso do comando tx para obter listas de palavras, ou mais genericamente, para transformar tum conjunto de caracteres em outro conjunto, como no Exemplo 5.5 na seco precedente, & uma prética ferramenta do idioma Unix a ser lembrada. Ela leva naturalmente a uma solucao de um problema que tivemos ao escrever este livro: como garantir uma marcagéo consistente 0 longo de 50K linhas de texto em arquivos de manuscrito? Por exemplo, um comando pode estar marcado com tr quando falamos sobre isso no texto corrido, mas em algum outro lugar, podemos ter dado um exemplo de algo que voc® digitou, indicado pela mareagio <1iteral>tr. Uma terceira possibilidade & uma referencia em pagina de manual, na forma tr (2). programa tagiist no Exemplo 5.6 oferece uma solugao. Ele encontra toxlos pares de tags de infcio/fim escritas na mesma linha e imprime uma lista ordenada que associa 0 uso da tag com os arquivos de entrada. Adicionalmente, ele marca com uma flecha casos em que a mes- ma palavra € marcada em mais de uma forma. Bis um fragmento de sua safda do arquivo de uma versto deste capstulo: § taghiet chOS aml 2 eur comand cchos xen * Na verdade, 2 tnica paler relacionada a raiz de “computador” que Shakespeare usou é “computa”, apenas uma vez em «ada uma de duas pegas, Comedy of Errors e King Richard Il. “Actwética” ocore seis vezes em suns pegs, “caleular” duas, ‘¢“matemética” us vezes. 120 _ Classic Shel Sriting Lout emphasis cch0S xen < 2 unig command cchos xen 1 unig emphasis ch0S. xn. < 1 vEstab flename cch0S. xn) A tarefa de listar fags € razoavelmente complexa e poderia ser bem dificil de fazer em lingua- gens de programago convencionais, mesmo aquelas com grandes classes de bibliotecas, tais, como C+ e Java, e mesmo que vocé comece com os programas de Knuth e Hanson para algo similiar ao problema de freqiiéncia de palavras. Apenas nove passos em um pipeline Unix. com as ferramentas agora jé familiares sio suficientes, O programa de freqiiéncia de palavras nao lidou com nomes de arquivos: ele apenas assumiu 0 stream de dados de entrada, Essa ndo é uma limitagdo séria, porque podemos facilmente alimenté-lo com miiltiplos arquivos de entrada com o cat. Aqui, porém, precisamos do nome do arquivo, j& que nao € stil para n6s reportarmos o problema sem dizermos onde cle esté. O nome do arquivo € 0 tinico argumento de tagl ist, disponivel no script como $1. 1. Alimentamos o primeiro arquivo de entrada no pipeline com 0 cat. Poderfamos, claro, eliminar este passo redirecionando a entrada do préximo passo a partir de §1, mas acha- mos que em pipelines complexos € mais claro separar a produgdo de dados do proces- samenio de dados. Também se tora um pouco mais fécil inserir ainda outro estigio no pipeline se 0 programa evoluir posteriormente. cat "$1" | 2. Aplicamos sed para simplificar a complexa marcagdo necesséria para URLs da web: sed -e ‘sHsysteniten *role=turl"#URLEg! \ -e 'sH/systemitens/uRLs' | Isso converte fags como para tags mais si ples, e ¢/oRi>, respectivamente. 3. O proximo estigio usa o tr para substituir espacos e pares de delimitadores por caracte- res nova linha: te OC JET \n\ala\n\a\a\ns |. 4. Neste ponto, a entrada consiste de uma “palavra” por linha (ou Tinhas em branco). Pala- vas so ou texto real ou fags SGML/XML. Usando ecrep, 0 préximo estfgio seleciona palavras circundads por rags: core te [*er]4 é dividida em quatro campos: um campo vazio, seguido por um Literal, tr, e /1iteral. nome de arquivo ¢ passado para 0 awk na linha de comando, onde a opgio -v define a varivel PILE do awk para o nome do arquivo. Essa varivel € entio usada pelo comando de impress, que imprime a palavra, a tag e 0 nome do arquivo: | awk -FY feo]! -v FInR=si" \ H{ print£("$-3is\c8-15s\tteln", $3, $2, FILE) ]' | .. 6. Ocestégio do sort ordena as linhas em ordem de palavras: CAPITULO 5 * Pipelines Podem Fazer Coisos Impressionantes 121 5.6 | sort |... 7. O comando unig fornece 2 contagem inicial de campos. A safda ¢ uma list sem que os campos $20 contagem, palavra, tag, arquivo: | unig -c | 8. Um segundo sort ordena a safda por palavras e tags (0 segundo ¢ terceiro campos): | sore -K2,2 -42,3 | 9. Ocestigio final usa um pequeno programa avk para filtrar linhas sucessivas, adicionando uma seta final quando ele vé a mesma palavra na linha anterior. Essa seta, ent, clara- mente indica insténeias em que palavras foram marcadas de forma diferente e, assim, merecem uma inspegdo mais de perto dos autores, dos editores, ou da equipe de produgo do livro. de registro- [awk 1 print (52 == Last) ? (50 " <- ast = §2 ) O programa completo ¢ apresentado no Exemplo 5-6. Exemplo 5-6 Fazendo uma lista de tags SGML 41 /bin/sh - # 18 un arquivo HTML/SCML/KML, Eornecido na linha de conando, contendo linhas de warcagdo cono palavra imprime na saida padréo una lista separada por {\it tags) de ys $0 contagen palavra tag arquivo crdenaéa de forma crescente pela palavra e tag 4 4 4 4 # 4 4 4 # Uso 4 tagliet sml-file cat "81" | sed -0 'stsyateniton *role=turl "#URLES! tr! Of }CI* ‘a\n\n\n\n\n\a" | egrep '>[*ea]+e/" | ‘awk -F! [eo] " -v PILB="$1" \ e 'ot/systenitem#/URLH* | +{ peinté(*-326\t8-25s\tts\a", $3, $2, FILE) }* | sort | unig -

You might also like