Visite também: UnderLinux ·  VivaOLinux ·  LinuxSecurity ·  Dicas-L ·  NoticiasLinux ·  SoftwareLivre.org ·  [mais] ·  Efetividade ·  Linux in Brazil ·  Floripa  

Botequim do Júlio Neves: o comando paste e dicas de variáveis do bash

Continuando a nova série iniciada aqui no BR-Linux no mês passado, o professor Julio Neves, autor do popular livro 'Programação Shell Linux', que recentemente teve publicada sua sexta edição, enviou mais um exemplar da sua série "Papo de Botequim", com artigos mensais sobre shell scripts. A série inicial, composta por 11 capítulos publicados pela Linux Magazine, encerrou recentemente. Mas como se trata de conteúdo que acho muitíssimo interessante, e o Julio é uma pessoa sempre disposta a compartilhar seus conhecimentos com a comunidade, achei que valia a pena oferecer um mecanismo que permitisse a continuação dessa disseminação de conhecimento.

Veja abaixo a íntegra do segundo artigo da nova série, falando sobre o comando 'paste' e dando algumas dicas sobre variáveis do ambiente. Veja também o capítulo anterior, falando sobre named pipes. Para ver mais material sobre shell publicado pelo Julio, visite www.julioneves.com - lá tem até um livro completo sobre Shell (é a coletânea dos artigos anteriores do Papo de Botequim, com 154 páginas A-4).


O comando paste



O paste é um comando pouco usado por sua sintaxe ser pouco conhecida. Vamos brincar com 2 arquivos criados da seguinte forma:

$ seq 10 > inteiros
$ seq 2 2 10 > pares

Para ver o conteúdo dos arquivos criados, vamos usar o paste na sua forma careta:

$ paste inteiros pares
1         2
2         4
3         6
4         8
5         10
6
7
8
9
10

Agora vamos transformar a coluna do pares em linha:

$ paste -s pares
2        4         6         8         10

O separador default é TAB, mas isso pode ser alterado com a opção -d. Então para calcular a soma do conteúdo de pares primeiramente faríamos:

$ paste -s -d'+' pares # também poderia ser -sd'+'
2+4+6+8+10

e depois passaríamos esta linha para a calculadora (bc) e então ficaria:

$ paste -s -d'+' pares | bc
30

Assim sendo, para calcular o fatorial do número contido em $Num, basta:

$ seq $Num | paste -sd'*' | bc

Com o comando paste você também pode montar formatações exóticas como esta a seguir:

$ ls | paste -s -d'\t\t\n'
arq1         arq2         arq3
arq4         arq5         arq6

O que aconteceu foi o seguinte: foi especificado para o comando paste que ele transformaria linhas em colunas (pela opção -s) e que os seus separadores (é...! Ele aceita mais de um, mas somente um após cada coluna criada pelo comando) seriam uma TAB, outra TAB e um ENTER, gerando desta forma a saída tabulada em 3 colunas. Agora que você já entendeu isto, veja como fazer a mesma coisa, porém de forma mais fácil e menos bizarra e tosca, usando o mesmo comando mas com a seguinte sintaxe:

$ ls | paste - - -
arq1         arq2         arq3
arq4         arq5         arq6

E isto acontece porque se ao invés de especificarmos os arquivos colocarmos o sinal de menos (-), o comando paste os substitui pela saída ou entrada padrão conforme o caso. No exemplo anterior os dados foram mandados para a saída padrão (stdout), porque o pipe (|) estava desviando a saída do ls para a entrada padrão (stdin) do paste, mas veja o exemplo a seguir:

$ cat arq1
predisposição
privilegiado
profissional
$ cat arq2
encher
mário
motor
$ cut -c-3 arq1 | paste -d "" - arq2
preencher
primário
promotor

Neste caso, o cut devolveu as três primeiras letras de cada registro de arq1, o paste foi montado para não ter separador (-d"") e receber a entrada padrão (desviada pelo pipe) no traço (-) gerando a saída juntamente com arq2.

Dicas de variáveis do Bash



Para terminar, vou trocar com vocês três pequenas dicas sobre variáveis intrínsecas do Bash que têm seu uso muito subutilizado (será que é por serem pouco conhecidas?):
OBS: Até aqui usei o prompt ($PS1) simbolizado pelo cifrão ($). Para facilitar a compreensão, daqui para a frente vou usar o meu prompt padrão (default).

Dica 1 - Repare esta seqüência de comandos no prompt:

/home/jneves> cd bin
-bash: cd: bin: No such file or directory
/home/jneves> CDPATH=/usr/local
/home/jneves> cd bin
/usr/local/bin
/usr/local/bin>

Com esse exemplo eu quis mostrar que a variável CDPATH atua como a PATH, sendo que esta última contém os diretórios que devem ser percorridos na procura de arquivos e a primeira contém os os diretórios que devem ser percorridos na procura por subdiretórios.
Para agilizar o meu lado, repare o conteúdo definido para esta variável no meu .bash_profile:

/home/jneves> echo $CDPATH
.:..:~

Desta forma, quando eu faço um cd, os subdiretórios serão pesquisados no diretório corrente, no seu diretório pai e no meu diretório home, nesta ordem.
Não resisto à tentação, mas já que falamos na variável PATH, que tal usarmos o comando tr para facilitar a legibilidade do seu conteúdo:

/home/jneves> echo $PATH
/bin:/usr/bin:/sbin:~:.
/home/jneves> echo $PATH | tr ':' '\n'
/bin
/usr/bin
/sbin
~
.

Neste exemplo o tr trocou os dois-pontos (:) por new-line (ENTER), facilitando a leitura do conteúdo da variável.

Dica 2 - Quando você executa diversos comandos encadeados em um pipe (|), o código de retorno (return code) dado por echo $? reflete apenas o resultado de saída do último comando executado no pipe. O vetor (array) PIPESTATUS, por sua vez, armazena em cada elemento o resultado respectivo de cada um dos comandos do pipe. Assim sendo, ${PIPESTATUS[0]} tem o código de retorno do primeiro comando, ${PIPESTATUS[1]} contém o código de retorno do segundo, e assim por diante.

O exemplo a seguir mostra um script que executa um pipeline de três comandos, e imprime o código de retorno de cada um deles:

/home/jneves> date | grep Wed | wc -l
/home/jneves> echo ${PIPESTATUS[*]}
0 1 0

Esta linha de código idiota que nos serve de exemplo, produziu no vetor ${PIPESTATUS} o seguinte: 0 (zero) indicando o sucesso do comando date, 1 indicando que o grep falhou ao procurar pela cadeia Wed, e novamente 0 (zero) para o sucesso do comando wc -l.

Dica 3 – Suponha que você queira que o operador confirme algum evento. O normal seria fazer:

read -n 1 -p "Confirma? " SN

e neste caso estaríamos alocando a variável $SN desnecessariamente pois ela será usada somente uma vez quando testarmos a escolha do operador, mas continuará ocupando memória até o fim do script (ou até que encontre um unset SN). Se fizéssemos:

read -n 1 -p "Confirma? "

A opção tomada pelo operador estaria armazenada na variável $REPLY, até que houvesse outra leitura. Experimente aí no seu prompt.

Aquele chope



Daqui a 30 dias darei outras dicas, mas para tirar dúvidas rápidas de Shell, é só ir tomar um chope em www.julioneves.com. Repare a caixa de diálogos colocada no canto superior esquerdo de cada página, porque ela serve para pesquisar o texto e os exemplos do comando que você está em dúvida, como se fosse um manual de referência.

BR-Linux.org
Linux® levado a sério desde 1996. Notícias, dicas e tutoriais em bom português sobre Linux e Código Aberto. "A página sobre software livre mais procurada no Brasil", segundo a Revista Isto É.
Expediente
Sobre o BR-Linux
Enviar notícia ou release
Contato, Termos de uso
FAQ, Newsletter, RSS
Banners e selos
Anunciar no BR-Linux
BR-Linux apóia
LinuxSecurity, Tempo Real
Suporte Livre, Drupal
Verdade Absoluta
Pandemonium
Efetividade, Floripa.net
sites da comunidade
Ajuda
Moderação
Flames: não responda!
Publicar seu texto
Computador para Todos
Notícias pré-2004
Tutoriais, HCL pré-2004