logo titulo
anterior indice proximo

Utilitários para manipulação de textos


Manipulação e processamento de textos em Linux é extremamente importante, pois quase todos os documentos são de uma forma ou de outra textos. Programas fonte, arquivos de configuração, imagens [20], tabelas de bancos de dados, logs do sistema, correio eletrônico (e-mails), ou mesmo documentos para publicação (troff, TeX, lout), são na maioria das vezes simples textos. Esta generalidade, que aparenta ser restritiva, na realidade resulta numa maior facilidade no processamento desses arquivos, melhor visualização do seu conteúdo e muitas vezes economia de espaço. Por exemplo, um arquivo .xpm é na maioria das vezes metade do tamanho de um arquivo .bmp (usado pelo MS-Windows), mais facilmente editado, e pode ser diretamente incorporado a um programa C como estrutura de dado.

O modo mais direto de se processar um texto é via um editor de textos (claro!), e para isso, já temos o nosso amigo joe. Os usuários com tradição em uso do Unix, certamente escolherão o vi (ou o emacs, mas não vamos provocar uma guerra aqui!). Estes dois últimos têm suas virtudes e são muitos mais completos que o nosso joe. Mas para nós, mortais, que já sofremos bastante tempo com "aquele" sistema operacional de brinquedo, como falamos no início, podemos ser mais modestos na nossa escolha. Entretanto processamento de texto não é somente uma edição interativa. Podemos realizar transformações múltiplas simultâneas em um arquivo, separar o arquivo em vários, converter em formas diferentes, ordenar, etc. Vejamos alguns dos programas que realizam tais proezas.

utilitários para
manipulação de

 processamento e manipulação de textos  

Muitos dos comandos tradicionais do Unix se encontram no pacote "GNU textutils". Outros são fornecidos separadamente, mas quase sempre sob o nome "GNU-alguma-coisa". Por isso mesmo, alguns preferem chamar o Linux de GNU/Linux.

Dentre os textutils, cat mostra um arquivo completo, head somente a parte inicial (controlável), tail somente a parte final (últimas n linhas).
Os comandos expand e unexpand transformam tabs em espaços e vice-versa. Para quebrar o arquivo em "pedaços", isto é, vários arquivos menores, temos o split. Para garantir a integridade do arquivo, cksum (existem outros programas com esse mesmo fim). Para ordenar (com várias opções) temos o sort, e o uniq remove linhas duplicadas, geralmente logo após executar um sort. Contamos bytes (caracteres), palavras e linhas do arquivo com wc. Os programas cut e paste se completam, recortando partes (colunas) de um arquivo e realizando a "colagem" de vários arquivos produzindo um arquivo com linhas maiores. Para numerar linhas, nl pode ser usado; tr para traduzir classes de caracteres em outros; od para traduzir arquivos (binários ou não) em várias formas: octal, decimal ou hexadecimal, com/sem texto ascii correspondente.
Outro utilitários são banner, para escrever letras "grandes" no terminal, e cal para mostrar um calendário (até mesmo com o calendário juliano!).

Vejamos uma rápida ficha técnica dos utilitários mais comuns (os argumentos são mostrados na forma <argumento>, o que for opcional será colocado entre colchetes) :

cat [<arquivo>]

Mostra o conteúdo do arquivo (texto) que é dado como argumento. Provavelmente, less (ou o velho more) sejam melhores para navegar.

head [-n<linhas>] <arquivo>

Mostra as primeiras linhas do arquivo.

tail [-n<linhas>] <arquivo>

Mostra as últimas linhas do arquivo.

sort [-o<saida>] [<arquivo>]

Ordena o arquivo (ou stdin) escrevendo no stdout (opcionalmente no arquivo <saida>).

expand [<arquivo>]

Expande tabs em espaçso e escreve em stdout.

unexpand [<arquivo>]

Converte (quando possível) múltiplos espaços em tabs. O contrário de expand.

uniq

Funciona como um filtro, lendo do stdin e escrevendo no stdout, removendo linhas duplicadas. (normalmente usado após um sort)

wc [-clw] [<arquivo>]

Devolve número de caracteres, linhas e palavras do arquivo (ou stdin).

cksum <arquivo>

Mostra cehcksum (CRC) e tamanho em bytes do arquivo.

sort [-o<saida>] [<arquivo>]

Ordena o arquivo (ou stdin) escrevendo no stdout (opcionalmente no arquivo <saida>).

expand [<arquivo>]

Expande tabs em espaçso e escreve em stdout.

unexpand [<arquivo>]

Converte (quando possível) múltiplos espaços em tabs. O contrário de expand.

cut e paste


Os utilitários cut e paste servem para extrair partes (campos) de um arquivo e remontá-las formando um arquivo novo, com dados possivelmente de vários outros arquivos. O comando cut pode extrair caracteres (com -c<lista de caracteres>) ou campos (com -f<lista de campos>), onde as listas podem ser números separados por vírgulas ou faixas de números como n1-n2 (separados por um hífen), ou ainda combinações de ambos. O delimitar de campos é um único caracter, especificado como -d<delim>.
Um exemplo ilustra melhor. Suponhamos que desejamos extrair o login (primeiro campo) e o nome real (campo 5) dos usuários do nosso sistema. A tabela seguinte nos mostra o efeito do comando:

arquivo /etc/passwd original após cut -f1,5 -d: /etc/passwd
guest::405:100:convidado especial:/home/guest:/bin/bash
rildo:gfTMTkLpLeupE:500:100:Rildo Pragana:/home/rildo:/bin/bash
postgres::65:1:Administrador do PostgreSQL:/usr/local/pgsql:/bin/bash
julius:toR8GcUaAr8h6:601:100:Julius Pragana:/home/julius:/bin/bash
--> guest:convidado especial
rildo:Rildo Pragana
postgres:Administrador do PostgreSQL
julius:Julius Pragana

O paste faz exatamente o contrário. Adiciona colunas provenientes de dois ou mais arquivos formando um arquivo final com estes dados. Vejamos um exemplo, usando a vírgula como delimitador:

arq1.txt:

guest
rildo
julius

arq2.txt:

405
500
601

paste -d, arq1.txt arq2.txt
arquivo resultante: (ou stdout)

guest,405
rildo,500
julius,601


banner cal e date

banner cria textos grandes, próprios para títulos (página de rosto) em listagens de programas.
cal mostra um calendário, opcionalmente para o mes e/ou ano que fornecermos. (o default é para o mes corrente)
Para mostrar de forma compacta a data e hora, como também para modificá-la, usamos o comando date.

cal+date

banner

expressões regulares


Programas como o grep, sed e awk, entre outros (mesmo o nosso amigo joe), se utilizam de uma descrição genérica de textos, na forma de padrões, para especificar alguns de seus argumentos. Formas com wildcards, como vimos com o shell, não são poderosas o suficientes para definirem padrões genéricos de caracteres que desejamos encontrar. Para isso, precisamos de uma notação mais abrangente, que são as expressões regulares.

Uma expressão regular descreve uma sequência de caracteres, casando letras adjacentes. O padrão mais simples é apenas um grupo de caracteres. Se quisermos, por exemplo, saber se em um determinado arquivo [21] existe a palavra exemplo, o comando grep[22] pode nos ser útil:

~$ grep exemplo livro
de espaço. Por exemplo, um arquivo .xpm é na maioria das vezes metade

Nesse exemplo, apenas uma ocorrência da palavra foi encontrada pelo programa grep. A nossa expressão regular era apneas a sequência de caracteres 'e','x','e','m','p','l','o'. De modo mais geral, podemos incluir um '.' (ponto) para indicar um caracter qualquer. Assim, a expressão movid.s "casa" (match em inglês) com movidos e movidas, mas casa também com movidxs, ou qualquer outro caracter no lugar do ponto. Para forçar que uma posição case apenas com alguns dentre uma classe de caracteres, podemos definir essa classe entre colchetes. Por exemplo movid[ao]s, so dá certo com a e o na posição dos colchetes.
Podemos definir igualmente classes que não contenham determinados caracteres. Por exemplo, a expressão regular d[^ao]s casa com d+<qualquer caracter exceto "a" ou "o">+s. Existem também caracteres especiais (chamados meta-caracteres), que modificam o comportamento de um padrão. O asterisco indica "qualquer quantidade (zero ou mais)" do caracter ou classe que o precede. O símbolo "+" (mais), indica "um ou mais". Exemplo: as+a casa com asa, assa, asssssa, etc., mas não com aa. Entretanto, por exemplo as*a pode casar com aa (o que com o "+" não podia).

Para marcar o começo ou final de uma linha, existem dois meta-caracteres: "^" e "$", respectivamente. Exemplo: ^$ é uma expressão regular que só casa com linhas em branco (inclusive sem nehum espaço ou caracter tab).

Um problema pode nos ocorrer quando queremos casar com um destes meta-caracteres literalmente. Exemplo, queremos procurar linhas que terminam com um ponto (final de parágrafo?!) no nosso documento. Usaremos o met-caracter de final de linha "$", juntamente com um ponto... Mas, espere aí, um ponto significa "um caracter qualquer, portanto, todas as linhas serão candidatas! Para retirar esse efeito "meta" destes caracteres especiais, prefixamos ele com uma barra de divisão invertida (exatamente como no shell): \.$ será nossa expressão regular.

Uma notação complementar serve para indicarmos "entre n e m caracteres" para o caracter ou classe precedente: {n,m}. Exemplo queremos um ou dois carcteres s apenas na expressão: as{1,2}a , que casa com asa e assa e mais nada!

A essa altura voce deve ter percebido que muitos destes caracteres e meta-caracteres conflitam com o shell, isto é, têm significado especial também para o shell. Portanto, voce terá que remover esse significado efetuado o quoting das expressões ou prefixando cada caracter especial com uma barra invertida para evitar que o shell faça suas substituições na linha de comando, antes de dar chance ao grep de conhecê-los.

o sed em poucas palavras

O sed, abreviatura de stream editor, é um programa que permite a edição de documentos de forma não-interativa.
Em outras palavras, ele permite automatizar a edicão de um documento, substituindo frases, adicionando, modificando (substituindo), e o seu funcionamento depende de expressões regulares.

Não daremos um curso completo de sed, pois ele é relativamente complexo. Apenas mostraremos exemplos que podem ser úteis no dia-a-dia. (observe que estamos colocando a expressão regular entre apóstrofes, para evitar a interpretação do shell, apesar de que neste caso nenhum caracter especial está sendo usado, mas é bom se acostumar assim...)

sed 's/PE/Pernambuco/' lista-telefonica

Troca abreviaturas de PE (Pernambuco) pelo nome completo no arquivo lista-telefonica. Neste caso, estamos usando o comando s (substitui) do sed para realizar a substituição. Mas observe que o resultado não é escrito de volta no arquivo, mas na saida padrão (stdout). Se não existisse o segundo parâmetro (lista-telefonica), a entrada viria de stdin.

Um exemplo mais sofisticado: o comando man formata a manpage produzindo um "texto" que contêm backspaces para "bater duas vezes" o mesmo caracter e dessa forma escrever em negrito (mesmo no terminal isso funciona, não é engraçado?). Se quisermos converter uma manpage em texto puro, devemos filtrar (eliminando) cada caracter (cópia) mais o backspace da saida do comando. Veja como podemos fazer isso com o sed. Para digitar um backspace no terminal (ou qualquer outro caracter de controle), digitamos primeiro Ctrl-v.

     man sed | sed 's/.\^H//g' | less

o less no final é para podermos visualizar. O ^H acima é o backspace (e não dois caracteres!). Finalmente o "g" no final do comando do sed indica que a substituição deve ser global, e não apenas para a primeira ocorrência da expressão regular.

O awk é uma linguagem também com expressões regulares, porém bem mais genérica que o sed (que é somente um editor de textos, na realidade). Uma linha de programa em awk é constituida de um padrão (expressão regular) e um comando a executar caso esta expressão seja "casada". Para cada linha do arquivo de entrada todas as expressões (linhas do programa) são tentadas.

awk


rpragana
Wed Jan 6 19:22:56 EDT 1999