Jak wydrukować wartości z pliku tekstowego do pliku z kolumnami za pomocą skryptu powłoki

11

Mam plik output.txt po uruchomieniu skryptu powłoki w następujący sposób:

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

Plik tekstowy ma wiele wpisów wiersz po wierszu w ten sam sposób. Chcę wydrukować te wartości w kolumnach: Nazwa pliku, Status i Datownik w następujący sposób:

Filename      Status        Timestamp
abc.txt     errorstatus1   Fri Nov 11 02:00:09 2016
def.txt     errorstatus2   Sat Nov 12 03:00:09 2016
linux09
źródło
4
Przykładowy format nie jest plikiem CSV, jest to plik o stałej szerokości kolumny. Możesz wyjaśnić pytanie lub podać poprawny przykład.
AlexP
Twój przykład nie jest formatem CVS. Format CVS to abc.txt,errorstatus1,Fri Nov 11 02:00:09 2016. Zredagowałem twoje pytanie, aby pasowało do tego, co mówi, z podanym przykładem. Cofnij się, ale pamiętaj, że naprawdę musisz wyjaśnić, czego dokładnie chcesz - wartości w kolumnach lub wartości oddzielone przecinkami
Sergiy Kolodyazhnyy,

Odpowiedzi:

14

Z paste:

paste - - - <file.txt

spowoduje to wyświetlenie zawartości pliku rozdzielonego znakiem nowej linii jako kolumn oraz trzech kolumn rozdzielonych tabulatorami w wierszu.

Dodanie nagłówka:

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

Aby skolumnizować wyniki, skorzystaj z pomocy column:

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

Przykład:

% 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
heemayl
źródło
Chłodny! Dzięki!! Ale jak wydrukować te wartości w formacie Excela. Chcę nagłówki kolumn w arkuszu programu Excel jako Status
nazwy pliku
@ linux09 Utwórz plik CSV i zaimportuj za pomocą programu Excel:echo Filename,Status,Timestamp; paste -d ',' - - - <file.txt
heemayl
Znakomity! Działa jak marzenie. Dziękuję bardzo
linux09,
6

Możesz użyć awk:

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

Wynik może nie być tak ładny:

$ 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

Możesz %s\tzamiast tego użyć wyjścia rozdzielonego tabulatorami.

  • NR % 3wynosi zero (i fałsz) dla każdej trzeciej linii, więc pozostałe linie są drukowane ze spacją po nich zamiast nowej linii. nextpo prostu rozpoczyna następną iterację.
  • Co trzecia linia jest drukowana „tak jak jest” z powodu ostatniej 1, z nową linią po niej, ponieważ nie pasuje do pierwszego bloku.
muru
źródło
5

Istnieje również rs( narzędzie hape 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.

W szczególności,

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

Więc

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

lub (aby dodać nagłówek)

$ { 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
steeldriver
źródło
3

Dla kompletności możesz to zrobić sedrównież:

sed -e '1iFilename\tStatus\tTimestamp' -e 'N;N;y/\n/\t/' file.txt
  • 1iFilename\tStatus\tTimestamp wstawia wiersz nagłówka przed wierszem 1
  • N;N wczytuje jeszcze dwa wiersze do bufora wzorców, dając w sumie 3 oddzielone wiersze nowego wiersza
  • y/\n/\t/ zastępuje wszystkie znaki nowej linii tabulatorami w buforze wzorów

Te i, Noraz ysed polecenia są opisane tutaj .

Cyfrowa trauma
źródło
Świetnie ... Czy mógłbyś również krótko skomentować użyte wyrażenia? dzięki!
Campa,
tak, idealny koleś
Campa
1

Zawsze można ugotować coś do przetwarzania tekstu za pomocą AWK lub Perla i oczywiście Pythona, co zapewnia ta odpowiedź.

Jako jednowarstwowy:

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

Jako skrypt wielowierszowy

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

Podstawową ideą jest podanie skryptu przez stdin (przy użyciu przekierowania powłoki <, chociaż można również użyć potoku). Skrypt używa tabulatorów do oddzielania pól, chociaż spacje mogą być również wykorzystane do uzyskania bardziej precyzyjnego wyniku.

Przykładowe dane wyjściowe na przykładzie danych wejściowych dostarczonych przez 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
Sergiy Kolodyazhnyy
źródło