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


11

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

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 possui várias entradas linha por linha da mesma maneira. Desejo imprimir esses valores em colunas: Nome do arquivo, Status e Timestamp da seguinte maneira:

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

4
O formato de exemplo não é um arquivo CSV, é um arquivo com largura de coluna fixa. Você pode esclarecer a pergunta ou fornecer um exemplo correto.
Alex12 # 12/12

Seu exemplo não é um formato CVS. O formato CVS é abc.txt,errorstatus1,Fri Nov 11 02:00:09 2016. Editei sua pergunta para corresponder ao que ela diz com o exemplo que você forneceu. Sinta-se livre para reverter, mas por favor note que você realmente precisa para esclarecer o que exatamente você quer - valores colunados ou valores separados por vírgulas
Sergiy Kolodyazhnyy

Respostas:


14

Com paste:

paste - - - <file.txt

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

Adicionando o cabeçalho:

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

Para colocar a saída em coluna, 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

Legal! Obrigado!! Mas como imprimir esses valores no formato excel. Eu quero os cabeçalhos das colunas na folha de excel como Matrícula Estado e Timestamp e os valores abaixo deles
linux09

@ linux09 Crie um CSV e importe com o Excel:echo Filename,Status,Timestamp; paste -d ',' - - - <file.txt
heemayl

Brilhante! Funciona como um encanto. Obrigado muito obrigado
linux09

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

Em %s\tvez disso, você pode usar para saída separada por tabulação.

  • NR % 3é zero (e falso) para cada terceira linha; portanto, as outras linhas são impressas com um espaço após elas, em vez de uma nova linha. nextapenas inicia a próxima iteração.
  • Cada terceira linha é impressa como está por causa da final 1, com uma nova linha após ela, pois ela não corresponde ao primeiro bloco.

5

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

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

3

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

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

Os comandos i, Ne ysed estão documentados aqui .


Ótimo .. Você também pode comentar brevemente as expressões que usou? valeu!
Campa

sim, cara perfeito
Campa

1

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

Como uma linha:

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 idéia básica aqui é fornecer a entrada do script via stdin (usando o redirecionamento do shell <, embora um pipe também possa ser usado). O script usa guias para separar os campos, embora os espaços também possam ser usados ​​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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.