2016-07-23 42 views
1

Der Versuch, die Ausgabe von einem Python-Client zu bereinigen. Dies ist ein Beispiel:Verwandeln Sie eine hübsch gedruckte Tabelle in eine einzelne Zeile mit Trennzeichen, indem Sie Awk verwenden.

+--------------------------+-----------+ 
| Text      | Test  | 
+--------------------------+-----------+ 
| 111-222-333-444-55555555 | 123456789 | 
| 111-222-333-444-55555555 | 123456789 | 
| 111-222-333-444-55555555 | 123456789 | 
+--------------------------+-----------+ 

I durch Entfernen der oben und unten mit durch Rohrleitungen die Ausgabe gestartet:

Command_Output | tail -n +4 | head -n -1 | 

So, jetzt haben wir folgendes:

| 111-222-333-444-55555555 | 123456789 | 
| 111-222-333-444-55555555 | 123456789 | 
| 111-222-333-444-55555555 | 123456789 | 

Jetzt I‘ Ich versuche, die Pipes in der Tabelle zu entfernen und die Tabelle in eine einzelne durch Kommas getrennte Zeile umzuwandeln. Es ist jedoch wichtig, dass die Korrelation zwischen den beiden Zahlen beibehalten wird, also sollte ich zwei Trennzeichen verwenden. Vielleicht sollte die endgültige Ausgabe wie folgt aussehen:

111-222-333-444-55555555~123456789,111-222-333-444-55555555~123456789,111-222-333-444-55555555~123456789 

So, jetzt ich an dieser Stelle bin:

Command_Output | tail -n +4 | head -n -1 | awk '{$3 = "~"; print $0;}' 

mir jemand mit dem letzten Teil helfen? Ich muss die Tabelle in eine einzelne, durch Kommas getrennte Zeile bringen.

+2

Die ganze Arbeit in einem einzigen durchgeführt werden ' awk' Befehl; keine Notwendigkeit für "Schwanz", "Kopf", "sed" auch. –

Antwort

0
:

... | awk ' 
    NR <= 3 || /^\+/ { next }       # skip header and footer 
    prev != "" && prev != $2 { printf "\n"; fsep="" } # see if new block is starting 
    { printf "%s", fsep $2 "~" $4; fsep=","; prev=$2 } # print line at hand 
    END { printf "\n" }        # print final newline 
' 

Um eine variable Anzahl von Spalten Griff

Danke für die Hilfe

+1

Sie brauchen nicht eine Menge anderer Werkzeuge und Rohre, wenn Sie awk verwenden. Auch dies ist auf genau 2 Eingabespalten beschränkt und beruht auf nicht-portablen sed bahavior ('\ n' für eine neue Zeile) und auf GNU awk (kein Leerzeichen nach' -v') und undefiniertem POSIX-Verhalten (sed erwartet) Eingabe mit keinem abschließenden Zeilenumbruch zu behandeln). –

2

Atomiklan's own answer funktioniert, aber:

  • zu einer einzigen Gruppe von Eingangsleitungen begrenzt ist, von denen alle der Ausgabe als eine Ausgangsleitung sind.

  • verwendet mehr GNU -spezifische Optionen, die auf Nicht-Linux-Plattformen im Allgemeinen nicht funktionieren werden.

  • verwendet externe Prozesse, wenn tun.

Eine verallgemeinerte Lösung, die jeden Block von Linien gibt selbigen (konzeptuell) ersten Spaltenwert als eine einzige Leitung teilen, übernimmt nur einen einzigen, POSIX-kompatibele awk Befehl (noch ein 2-column Layout):

... | awk -F ' *\\| *' ' 
    NR <= 3 || /^\+/ { next }       # skip header and footer 
    {             # process each data row 
    fsep=""; first=1 
    for (i=1; i<=NF; ++i) {       # loop over all fields 
     if ($i == "") continue       # skip empty fields 
     # See if a new block is starting and print the appropriate record 
     # separator.  
     if (first) { 
     if (prev != "") printf (prev != $i ? "\n" : ",") 
     prev=$i          # save record's 1st nonempty field 
     first=0          # done with 1st nonempty field 
     } 
     printf "%s", fsep $i       # print field at hand. 
     fsep="~"          # set separator for subsequent fields 
    } 
    } 
    END { printf "\n" }        # print trailing newline 
' 
0

Eine einfachere awk-basierte Lösung:

Command | awk -vORS=, '($1=="|" && NR>3) {print $2"~"$4}' 

Dies läßt jedoch eine Hinter , am Ende.Um dies zu beheben:

Command | awk -vORS= '($1=="|" && NR>3) {if (NR>4) {print ","}; print $2"~"$4}' 

die gibt:

111-222-333-444-55555555~123456789,111-222-333-444-55555555~123456789,111-222-333-444-55555555~123456789 
+2

Verführerisch einfach, aber (a) es ist im Allgemeinen nicht ratsam, die Kopfzeile von Datenzeilen nur durch ihren _content_ zu unterscheiden (es kann keine zuverlässige Unterscheidung geben) und (b) fügt Ihre Lösung ein nacheilendes ',' anstelle einer Zeilenumbruch hinzu zum Ausgang. – mklement0

+0

Behoben oben über die Verwendung von NR statt. –

+0

Besser, aber jetzt fehlt Ihnen ein abschließendes '\ n' (welche Dienstprogramme im Allgemeinen am Ende einer Datei erwarten). – mklement0

1

Dies wird für eine beliebige Anzahl von Eingabespalten in allen awks arbeiten:

$ awk -F ' *[|] *' -v OFS='~' 'NF>1 && ++c>1 {$1=$1; gsub(/^~|~$/,""); printf "%s%s", (c>2?",":""), $0} END{print ""}' file 
111-222-333-444-55555555~123456789,111-222-333-444-55555555~123456789,111-222-333-444-55555555~123456789