avalia vários padrões da saída do programa e grava em arquivos específicos de padrão

4

Eu tenho um script que gera alguns valores / números e quero dividi-los em dois arquivos. Eu estou olhando para algo como:

./runme.sh | grep 'ook' >> ook.out | grep 'eek' >> eek.out

Onde o segundo pipe não deve, como é o caso, obter a saída do primeiro grep, mas a do runme.sh. Isso é possível?

    
por Sardathrion 16.12.2011 / 12:57

5 respostas

6

Esse é o caso de uso perfeito para o utilitário pee .

./runme.sh | pee "grep ook >> ook.out" "grep eek >> eek.out"

No Debian & derivativos, pee é encontrado em moreutils package.

    
por 16.12.2011 / 13:25
7

Você deve fazer egrep para ambos os padrões.

'/. runme.sh | egrep "ook | eek"

mas parece que você precisa redirecionar a saída de avaliação de cada padrão para seu próprio arquivo, o qual grep parece não suportar. Alguém, por favor, corrija-me se for possível.

Edit: minaev deu um exemplo de trabalho com xixi de moreutils, mas se xixi está faltando em sua plataforma, ainda podemos usar tee como este. Apenas brinque com a substituição do processo.

./runme.sh |tee >(grep ook > ook.txt) >(grep eek > eek.txt)

Exemplo:

[centos@centos scripts]$ ./runme.sh
eekfarapplebin
keeekmajowrwt
keekookjsfskooeek
ook
[centos@centos scripts]$ ./runme.sh | tee >(grep eek >eek.txt) >(grep ook >ook.txt)
eekfarapplebin
keeekmajowrwt
keekookjsfskooeek
ook
[centos@centos scripts]$ cat eek.txt 
eekfarapplebin
keeekmajowrwt
keekookjsfskooeek
[centos@centos scripts]$ cat ook.txt 
keekookjsfskooeek
ook
[centos@centos scripts]$ 
    
por 16.12.2011 / 13:21
6

A alternativa simples awk :

./runme.sh | awk '/ook/{print>>"ook.out"}/eek/{print>>"eek.out"}'

Com pouca adição, o código awk pode ser facilmente expandido - basta colocar a matriz r, pois são necessários muitos pares de arquivos de saída de expressões regulares:

./runme.sh | awk 'BEGIN{r["ook"]="ook.out";r["eek"]="eek.out"}{for(i in r)if($0~i)print>>r[i]}'

O comando sed w é equivalente a > , infelizmente não há como anexar ao arquivo:

./runme.sh | sed -n $'/ook/wook.out\n/eek/week.out'
    
por 16.12.2011 / 14:17
3

Eu estou supondo que o runme é um comando de longa duração ou requer atomicidade (é executado uma vez).

Sugiro criar um nome de arquivo temporário exclusivo com mktemp

TMPFILE=$(mktemp)
./runme.sh > $TMPFILE
grep 'ook' $TMPFILE >> ook.out
grep 'eek' $TMPFILE >> eek.out
\rm -f $TMPFILE
    
por 16.12.2011 / 13:32
2

O comando tee pode manter uma cópia do fluxo canalizado em um arquivo temporário. Então podemos grep o stdout original e também o arquivo temporário separadamente:

./runme.sh |tee temp |grep ook >>ook.out;grep eek temp >>eek.out
    
por 16.12.2011 / 13:29