Como imprimir valores em um arquivo de texto para um arquivo em colunas usando o shell script

11

Eu tenho um output.txt da execução de um script de shell da seguinte forma:

abc.txt
errorstatus1
Fri Nov 11 02:00:09 2016
def.txt
errorstatus2.txt
Sat Nov 12 03:00:09 2016

O arquivo de texto tem várias entradas linha a linha da mesma maneira. Quero imprimir esses valores em colunas: nome do arquivo, status e carimbo de data e hora da seguinte forma:

Filename      Status        Timestamp
abc.txt     errorstatus1   Fri Nov 11 02:00:09 2016
def.txt     errorstatus2   Sat Nov 12 03:00:09 2016
    
por linux09 12.12.2016 / 13:12

5 respostas

14

com paste :

paste - - - <file.txt

isso gerará o conteúdo do arquivo separado por nova linha como colunas e três colunas separadas por tabulações por linha.

Adicionando o cabeçalho:

echo Filename Status Timestamp; paste - - - <file.txt

Para colocar em coluna a saída, obtenha ajuda de column :

{ echo Filename Status Timestamp; paste - - - <file.txt ;} | column -t

Exemplo:

% cat file.txt
abc.txt
errorstatus1
Fri Nov 11 02:00:09 2016
def.txt
errorstatus2.txt
Sat Nov 12 03:00:09 2016

% { echo Filename Status Timestamp; paste - - - <file.txt ;} | column -t
Filename  Status            Timestamp
abc.txt   errorstatus1      Fri        Nov  11  02:00:09  2016
def.txt   errorstatus2.txt  Sat        Nov  12  03:00:09  2016
    
por heemayl 12.12.2016 / 13:27
6

Você pode usar o awk:

awk 'NR % 3 {printf "%s ", $0; next}1'

A saída pode não ser tão bonita:

$ awk 'NR % 3 {printf "%s ", $0; next} 1' input
abc.txt errorstatus1 Fri Nov 11 02:00:09 2016
def.txt errorstatus2.txt Sat Nov 12 03:00:09 2016

Você pode usar %s\t para saída separada por tabulações.

  • NR % 3 é zero (e falso) para cada terceira linha, portanto as outras linhas são impressas com um espaço depois delas, em vez de uma nova linha. next apenas inicia a próxima iteração.
  • Cada terceira linha é impressa como está por causa da% final 1 , com uma nova linha depois dela, pois não corresponde ao primeiro bloco.
por muru 12.12.2016 / 13:19
5

Há também o utilitário hape rs (BSD r e s ):

DESCRIPTION
     rs reads the standard input, interpreting each line as a row of blank-
     separated entries in an array, transforms the array according to the
     options, and writes it on the standard output.  With no arguments it
     transforms stream input into a columnar format convenient for terminal
     viewing.

Em particular,

     -e      Consider each line of input as an array entry.

Então

$ rs -e < file
abc.txt                   errorstatus1              Fri Nov 11 02:00:09 2016
def.txt                   errorstatus2.txt          Sat Nov 12 03:00:09 2016

ou (para adicionar o cabeçalho)

$ { printf '%s\n' Filename Status Timestamp ; cat file ; } | rs -e
Filename                  Status                    Timestamp
abc.txt                   errorstatus1              Fri Nov 11 02:00:09 2016
def.txt                   errorstatus2.txt          Sat Nov 12 03:00:09 2016
    
por steeldriver 13.12.2016 / 02:19
3

Para completar, você pode fazer isso com sed também:

sed -e '1iFilename\tStatus\tTimestamp' -e 'N;N;y/\n/\t/' file.txt
  • 1iFilename\tStatus\tTimestamp insere a linha de cabeçalho antes da linha 1
  • N;N lê mais duas linhas no buffer padrão, dando um total de 3 linhas separadas de nova linha
  • y/\n/\t/ substitui todas as novas linhas com tabulações no buffer padrão

Os comandos i , N e y sed estão documentados aqui .

    
por Digital Trauma 13.12.2016 / 05:18
1

É sempre possível criar algo para processamento de texto com AWK ou Perl e, claro, Python, que é o que essa resposta fornece.

Como um marcador:

python -c 'import sys;print "Filename\tStatus\tTimestamp"; lines=[l.strip() for l in sys.stdin];print "".join([l+"\n" if i%3 == 0 else l+"\t" for i,l in enumerate(lines,1) ])' < input.txt

Como script de várias linhas

import sys
print "Filename\tStatus\tTimestamp"
lines=[l.strip() for l in sys.stdin]
print "".join([l+"\n" if i%3 == 0 else l+"\t" for i,l in enumerate(lines,1) ])

A ideia básica aqui é fornecer a entrada do script via stdin (usando o redirecionamento de shell < , embora um pipe possa ser usado também). O script usa guias para separar os campos, embora espaços possam ser usados também para uma saída mais "ajustada".

Exemplo de saída usando o exemplo de entrada fornecido pelo OP:

$ python -c 'import sys;print "Filename\tStatus\tTimestamp";                                   
> lines=[l.strip() for l in sys.stdin];
> print "".join([l+"\n" if i%3 == 0 else l+"\t" for i,l in enumerate(lines,1) ])' < input.txt
Filename    Status  Timestamp
abc.txt errorstatus1    Fri Nov 11 02:00:09 2016
def.txt errorstatus2    Sat Nov 12 03:00:09 2016
    
por Sergiy Kolodyazhnyy 13.12.2016 / 02:43