Redirecionando Saída de impressão para múltiplos arquivos no awk

7

Eu quero imprimir as mesmas linhas em dois arquivos diferentes. O que estou fazendo agora é:

print ID[i]" "Value[i]" "TS1[i]" "TS2[i] > "file1.txt";
print ID[i]" "Value[i]" "TS1[i]" "TS2[i] > "file2.txt";

Posso escrever um único comando para redirecioná-lo para dois arquivos diferentes?

EDITAR

Eu não quero imprimir toda a minha saída de comando para os vários arquivos, eu quero escrever alguns registros baseados em alguma condição em vários arquivos, estou imprimindo isso dentro do script awk , então eu preciso de um maneira eficiente de fazê-lo.

    
por Aashu 24.06.2014 / 11:27

4 respostas

9

Você não pode fazer isso com awk .

Usando tee , você pode fazer algo assim:

$ awk '{print ID[i]" "Value[i]" "TS1[i]" "TS2[i]}' file | tee out1 out2

Usando tee -a , se você deseja anexar, em vez de substituir os arquivos existentes.

Se você não quiser imprimir toda a saída, tente:

awk '
    BEGIN {outfile["a.txt"];outfile["b.txt"]}
    { for (file in outfile) { print > file } }' file
    
por 24.06.2014 / 11:44
10

Dentro de awk , em vez de redirecionar para um arquivo com print "text" > "file" , você pode redirecionar para um comando usando:

print "something" | "tee file1.txt file2.txt"

A primeira vez que você usa esse | , awk gera o comando, e na próxima vez que ele reutiliza o mesmo comando, ele não inicia um novo tee cada vez que você faz isso e não faz Sobrescreva os arquivos (você precisa chamar close("tee file1.txt file2.txt") se quiser que awk inicie um novo comando na próxima vez). No entanto, se você fizer os dois > "file1.txt" e | "tee file1.txt..." , haverá um conflito.

Você pode então usar >> "file1.txt" e | "tee -a file1.txt..." .

No entanto, eu ainda usaria a @ coonglm for approach ou usaria uma função awk , pois isso seria mais limpo e eficiente.

    
por 24.06.2014 / 13:31
4

Uma função definida pelo usuário pode tornar seu código mais limpo e causar menos duplicação, se é isso que a preocupação é.

function print_to_files( message, file_a, file_b ) {
   print message > file_a;
   print message > file_b;
}

message = sprintf( "%s %s %s %s", ID[i], Value[i], TS1[i], TS2[i] )
print_to_files( message , "filea", "fileb" );'

Ou codifique os arquivos se isso for tudo o que você precisa.

function print_to_files( message ) {
   print message > "/path/to/filea";
   print message > "/path/to/fileb";
}

message = sprintf( "%s %s %s %s", ID[i], Value[i], TS1[i], TS2[i] )
print_to_files( message );'
    
por 24.06.2014 / 13:37
3

Você pode fazer isso com sed - mas sem uma ideia mais clara de sua entrada, não sei como demonstrá-la especificamente. Ainda assim, aqui está um exemplo genérico:

seq 10 | sed -ne '/1/w ./onesfile.txt' -e '/3/w threesfile.txt'

Isso grava apenas as linhas que contêm 1 na onesfile.txt e, caso contrário, 3 - todo o resto é excluído. Este é um exemplo básico muito de como isso pode funcionar, mas se você puder fornecer uma amostra de entrada, eu posso fazer um pouco melhor.

Quando sed abre um arquivo para gravação, ele permanece aberto até que o processo seja concluído - ele não trunca continuamente suas próprias gravações - os descritores de arquivo são retidos durante a vida útil do processo.

    
por 24.06.2014 / 13:28