shell-script-pt
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RES: [shell-script] Arquivo TXT


From: Julio Cezar Neves - DATAPREVRJ
Subject: RES: [shell-script] Arquivo TXT
Date: Wed, 29 Dec 2004 14:19:46 -0300

Falou Beto,
é isso aí! A substituição de processos (process substitution) gera a saída
de um cmd em um arquivo tipo named pipe temporário. Para constar isso
execute o cmd a seguir:

Prompt>  ls -l >(cat)
l-wx------  1 jneves jneves   64 Dec 29 13:51 /dev/fd/63 -> pipe:[165010]

Como alguns cmds (como o paste da dúvida do colega) exigem como entrada
arquivos, a substituição de processos foi usada para gerá-los.

Abaixo trecho (desformatado) do meu livro que fala sobre o assunto:

===========================================>8CorteAqui8<====================
====================
O Shell também usa os named pipes de uma maneira bastante singular. Como já
vimos, quando um comando está entre parênteses, ele na realidade é executado
em um subshell. Como o Shell atual recebe uma saída única deste subshell, se
agruparmos diversos comandos sob um par de parênteses, esta saída poderia
ser redirecionada como uma unidade. Por exemplo, o comando:
$ (pwd ; ls -l)> saida.out

enviará a saída de dois comandos (o pwd e o ls -l) para o arquivo saída.out.
Uma substituição de processos (process substitution) ocorre quando você põe
um < ou um > grudado na frente do parêntese da esquerda. Teclando-se o
comando:
$ cat <(ls -l)  O < tem que estar colado no parêntese

Resultará no comando ls -l executado em um subshell como é normal, porém
redirecionará a saída para um named pipe temporário, que o Shell cria,
nomeia e depois remove. Então o cat terá um nome de arquivo válido para ler
(que será este named pipe e cujo dispositivo lógico associado é /dev/fd/63),
e teremos a mesma saída que a gerada pela listagem do ls -l, porém dando um
ou mais passos que o usual. Esta técnica chama-se process substitution ou
substituição de processos.
Similarmente dando >(comando) resultará no Shell nomeando um pipe temporário
do qual o comando dentro dos parênteses lê a entrada.
Você deve estar pensando que isto é uma maluquice de nerd, né? Então suponha
que você tenha 2 diretórios: dir e dir.bkp e deseja saber se os dois estão
iguais (aquela velha dúvida: será que meu backup está atualizado?). Basta
comparar os 2 diretórios com o comando cmp, fazendo:
$ cmp <(ls -la dir1) <(ls -la dir.bkp)

O comando cmp, cuja entrada só aceita arquivos, irá receber a listagem dos
dois diretórios como se fossem arquivos (named pipes temporários ou
/dev/fd/63), lê-los e compará-los.
Outro exemplo:
$ echo $impar
1 3 5 7
$ echo $par
2 4 6 8
$ paste <(echo $impar | tr " " "\012") <(echo $par | tr " " "\012")
1       2
3       4
5       6
7       8

No último exemplo, o comando tr transformou os espaços em branco das
variáveis impares e pares em <ENTER> (usei a notação octal \012, mas no
Linux poderia ter usado \n) e cada um destes grupamentos de comandos gerou
um arquivo temporário que pôde ser lido pelo paste.
Tanto o tar quanto o bzip2 necessitam de arquivos para serem felizes e
executar corretamente as suas atribuições. Então para gerarmos um arquivo do
tipo .tar.bz2 teríamos de executar primeiramente o tar e na sua saída
executar o bzip2. Usando a técnica de substituição de processos, poderíamos
fazer o mesmo de forma mais compacta conforme o exemplo a seguir:
$ tar cf >(bzip2 -c > arquivo.tar.bz2) $NomeDiretorio

Esmiuçando este exemplo: primeiramente é feito um tar no arquivo apontado
pela variável $NomeDiretorio e a sua saída é mandada para o arquivo
temporário /dev/fd/63, que é um named pipe usado para canalizar a saída do
comando tar para o bzip2, gerando desta maneira o arquivo.tar.bz2.
O último exemplo para atestar a versatilidade da substituição de processos
vem a seguir e é um fragmento de código extraído de um script da distro
SuSE:
while read  des what mask iface; do
#   comandos ...
done < <(route -n)  

Para testá-lo, vamos substituir comandos ... por alguma besteira sem
sentido, tal como:
while read des what mask iface; do
    echo $des $what $mask $iface
done < <(route -n)  

Que reproduziria a tabela de roteamento IP do kernel. Ourtra forma de
cumprir a mesma tarefa, porém mais fácil de entender do que esta seria a
seguinte:
route -n |
while read des what mask iface; do
    echo $des $what $mask $iface
done

Apesar desta forma de codificação produzir uma saída idêntica à anterior, o
uso do pipe (|) gera um subshell para a execução do laço (loop) while; do
... done e portanto alterações de valores de variáveis no seu interior
seriam perdidas ao término deste subshell. Assim sendo, se fizéssemos:
route -n | while read x
do
    ((y++))
done
echo $y

Não obteríamos saída alguma porque a variável $y não teria sido sequer
criada no Shell corrente, no entanto se fizéssemos:
while read x
do
    ((y++))
done < <(route -n)
echo $y

Teríamos como saída a quantidade de linhas gerados pelo comando route -n.
Já que estamos no finalzinho desta seção, que você teve tanta paciência para
ler, vejamos se a substituição de processos (process substitution) é mesmo
feita via um named pipe temporário:
$ ls -l >(cat)
l-wx------ 1 jneves jneves 64 Aug 27 12:26 /dev/fd/63 -> pipe:[7039]
$ ls -l >(cat)
l-wx------ 1 jneves jneves 64 Aug 27 12:26 /dev/fd/63 -> pipe:[7050]

É, realmente é um named pipe.
A substituição de processos também pode ser misturada, você pode ver que o
exemplo a seguir
$ cat <(cat <(cat <(ls -l)))

trabalha como uma forma muito redundante para listar o diretório corrente.
Como você pode ver, os named pipes, com uma pequena ajuda do Shell, permite
que árvores de pipes sejam criadas. As possibilidades são limitadas apenas
pela sua imaginação.
===========================================>8CorteAqui8<====================
====================

Julio
:wq

| -----Mensagem original-----
| De: oteb_04 [mailto:address@hidden]
| Enviada em: quarta-feira, 29 de dezembro de 2004 13:44
| Para: address@hidden
| Assunto: RES: [shell-script] Arquivo TXT
| 
| 
| 
| 
| Olá
| 
| >A explicação da construção <(...) é longa e eu já postei na lista há
| >uns 2
| >meses. Quem achar favor reproduzir.
| 
| Encontrei isso aqui:
| 
| "...uma saída muito mais elegante (porém muito pouco conhecida) que é
| através do uso de named pipes temporários, via substituição 
| de processo
| (process substitution), teste isso:
| 
| $ while read line
| > do
| > let i++ # Com o let não é necessário inicializar a variável (i=0)
| > echo -n $i
| > done < <(seq 10)
| 12345678910$
| ..."
| 
| A mensagem completa está em:
| http://br.groups.yahoo.com/group/shell-script/message/11444
| 
| Olhei no abs-guide:
| http://www.die.net/doc/linux/abs-guide/process-sub.html
| 
| e no primeiro paragráfo diz:
| Process substitution is the counterpart to command substitution.
| Command substitution sets a variable to the result of a command, as in
| dir_contents=`ls -al` or xref=$( grep word datafile). Process
| substitution feeds the output of a process to another process (in
| other words, it sends the results of a command to another command).
| 
| o que parece ser algo como:
| O process substitution(substituição de processo) é a contrapartida ao
| command substitution(comando de substituição). Este atribui a uma
| variável o resultado de um comando, como em
| 
|                    dir_contents=`ls -al` 
|                    ou
|                    xref=$(grep word datafile)
| 
| O process substitution(substituição de processo) alimenta, com a saida
| de um processo, um outro processo( em outras palavras; envia o
| resultado de um comando para outro comando)
| 
| obs: não existe espaço entre o direcionador e o parenteses
| 
| Além do exemplo acima, mais um(tirado do abs-guide):
| cat <(ls -l)
| # É o mesmo que     ls -l | cat
| 
| 
| abraço
| Beto
| 
| 
|     
| 
| 
| 
| 
| 
| 
| ---------------------------------------------------------------------
| Esta lista não admite a abordagem de outras liguagens de 
| programação, como perl, C etc. Quem insistir em não seguir 
| esta regra será moderado sem prévio aviso.
| ---------------------------------------------------------------------
| Sair da lista: address@hidden
| ---------------------------------------------------------------------
| Esta lista é moderada de acordo com o previsto em 
http://www.listas-discussao.cjb.net
---------------------------------------------------------------------
 
Links do Yahoo! Grupos




 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]