Come stampare i valori in un file di testo su file con colonne usando lo script della shell


11

Ho un output.txt da eseguire uno script di shell come segue:

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

Il file di testo ha più voci riga per riga nello stesso modo. Voglio stampare questi valori in colonne: Nome file, Stato e Timestamp come segue:

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

4
Il formato di esempio non è un file CSV, è un file a colonna fissa. Potresti voler chiarire la domanda o fornire un esempio corretto.
AlexP,

Il tuo esempio non è un formato CVS. Il formato CVS è abc.txt,errorstatus1,Fri Nov 11 02:00:09 2016. Ho modificato la tua domanda in modo che corrisponda a ciò che dice con l'esempio che hai fornito. Sentiti libero di tornare indietro, ma tieni presente che devi davvero chiarire cosa vuoi esattamente - valori colonnati o separati da virgole
Sergiy Kolodyazhnyy

Risposte:


14

Con paste:

paste - - - <file.txt

questo produrrà il contenuto del file separato da riga nuova come colonne e tre colonne separate da tabulazione per riga.

Aggiunta dell'intestazione:

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

Per catalogare l'output, ottenere aiuto da column:

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

Esempio:

% 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

Freddo! Grazie!! Ma come stampare questi valori in formato Excel. Voglio le intestazioni di colonna nel foglio Excel come Nome file e Timestamp e i valori sottostanti
linux09

@ linux09 Crea un CSV e importa con Excel:echo Filename,Status,Timestamp; paste -d ',' - - - <file.txt
heemayl

Brillante! Funziona come un fascino. Grazie mille
linux09

6

Puoi usare awk:

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

L'output potrebbe non essere così carino:

$ 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

È possibile utilizzare %s\tinvece per l'output separato da tabulazioni.

  • NR % 3è zero (e falso) per ogni terza riga, quindi le altre righe vengono stampate con uno spazio dopo di esse anziché una nuova riga. nextinizia solo la prossima iterazione.
  • Ogni terza riga viene stampata così com'è a causa della finale 1, con una nuova riga dopo di essa, poiché non corrisponde al primo blocco.

5

C'è anche rs( utilità hape 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.

In particolare,

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

Così

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

oppure (per aggiungere l'intestazione)

$ { 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

Per completezza, puoi farlo sedanche con :

sed -e '1iFilename\tStatus\tTimestamp' -e 'N;N;y/\n/\t/' file.txt
  • 1iFilename\tStatus\tTimestamp inserisce la riga di intestazione prima della riga 1
  • N;N legge altre due righe nel buffer di pattern, fornendo un totale di 3 righe separate di nuova riga
  • y/\n/\t/ sostituisce tutte le nuove righe con le schede nel buffer dei pattern

I comandi i, Ne ysed sono documentati qui .


Ottimo .. Potresti anche commentare brevemente le espressioni che hai usato? grazie!
Campa,

sì, amico perfetto
Campa,

1

È sempre possibile preparare qualcosa per l'elaborazione del testo con AWK o Perl, e ovviamente Python, che è ciò che questa risposta fornisce.

Come one-liner:

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

Come script multilinea

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) ])

L'idea di base qui è quella di fornire l'input dello script tramite stdin (usando il reindirizzamento della shell <, sebbene si possa usare anche una pipe). Lo script utilizza le schede per separare i campi, sebbene gli spazi possano essere utilizzati anche per un output più "perfezionato".

Output di esempio utilizzando l'esempio di input fornito da 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.