2016-08-08 8 views
-2

ich eine txt-Datei wie folgt formatiert:Wie Linien von TXT oder CSV mit bestimmten Mustern löschen

Das Ziel ist es, die Reihen zu entfernen, die mit dem Wort „Teilsumme Gruppe 1“ oder „Teilsumme Gruppe 2“ beginnen oder "Grand Total" (solche Strings stehen immer am Anfang der Zeile), aber ich muss sie nur entfernen, wenn der verbleibende Teil der Zeile leere Felder enthält (oder mit Leerzeichen gefüllt ist).

Es könnte mit awk oder sed (1 pass) erreichbar sein, aber ich mache derzeit mit 3 separaten Schritten (eins für jeden Text). Eine generische Syntax wäre großartig. Danke an alle.

Meine txt-Datei sieht wie folgt aus:

Some Generic Headers at the beginning of the file 
======================================================================= 
Group 1 
======================================================================= 
6.00 500 First Line Text          1685.52 
1.00 502 Second Line Text          280.98 
     530 Other Line text          157.32 
_________________________________________________________________________ 
Subtotal Group 1 
Subtotal Group 1 
Subtotal Group 1 
Subtotal Group 1            2123.82 
Subtotal Group 1 
Subtotal Group 1 

======================================================================== 
GROUP 2 
======================================================================== 

7.00 701 First Line Text          53.63 
     711 Second Line text          97.85 
7.00 740 Third Line text          157.32 
     741 Any Line text           157.32 
     742 Any Line text           18.04 
     801 Last Line text          128.63 
_______________________________________________________________________ 
Subtotal Group 2 
Subtotal Group 2 
Subtotal Group 2 
Subtotal Group 2 
Subtotal Group 2             612.79 
Subtotal Group 2 
_______________________________________________________________________ 
Grand total 
Grand total 
Grand total 
Grand total 
Grand total 
Grand total 
Grand total              1511.03 

Ziel Ausgang ich zu erreichen bin versucht:

Some Generic Headers at the beginning of the file 
======================================================================= 
Group 1 
======================================================================= 
6.00 500 First Line Text          1685.52 
1.00 502 Second Line Text          280.98 
     530 Other Line text          157.32 
_______________________________________________________________________ 
Subtotal Group 1            2123.82 

======================================================================= 
GROUP 2 
======================================================================= 

7.00 701 First Line Text          53.63 
     711 Second Line text          97.85 
7.00 740 Third Line text          157.32 
     741 Any Line text           157.32 
     742 Any Line text           18.04 
     801 Last Line text          128.63 
_______________________________________________________________________ 
Subtotal Group 2             612.79 
_______________________________________________________________________ 
Grand total              1511.03 
+0

Was sind 'Field1, ...' Ziffern? Beginnen sie mit etwas anderem als "Zwischensumme" oder "Gesamtsumme"? –

+0

@David Du hast Recht, es ist ziemlich verwirrend, ich werde die Frage bearbeiten. Vielen Dank. –

+0

@EdMorton Ich hatte eine CSV (und Sie haben mir in den letzten Tagen sehr geholfen, es zu formatieren und in einen lesbaren formatierten Text zu konvertieren, mit Alignement). Jetzt, wo ich einen fast druckbaren txt erreiche, ist das Letzte, was behoben werden muss, überflüssige unbrauchbare Zeilen zu entfernen. Wahrscheinlich hätte es früher sein können, mit einer effizienteren Codierung, aber ich bin nicht so geschickt darin, alle Schritte in einem einzigen Skript zu verstehen, also gehe ich schrittweise vor. Danke Ed! –

Antwort

1

Das ist ein Job, für den grep erfunden wurde:

$ grep -Ev '^(Subtotal Group [0-9]+|Grand total)[[:blank:]]*$' file 
Some Generic Headers at the beginning of the file 
======================================================================= 
Group 1 
======================================================================= 
6.00 500 First Line Text          1685.52 
1.00 502 Second Line Text          280.98 
     530 Other Line text          157.32 
_________________________________________________________________________ 
Subtotal Group 1            2123.82 

======================================================================== 
GROUP 2 
======================================================================== 

7.00 701 First Line Text          53.63 
     711 Second Line text          97.85 
7.00 740 Third Line text          157.32 
     741 Any Line text           157.32 
     742 Any Line text           18.04 
     801 Last Line text          128.63 
_______________________________________________________________________ 
Subtotal Group 2             612.79 
_______________________________________________________________________ 
Grand total              1511.03 

Sie können das gleiche regexp in awk verwenden oder sed wenn Sie es vorziehen:

awk '!/^(Subtotal Group [0-9]+|Grand total)[[:blank:]]*$/' file 
sed -E '/^(Subtotal Group [0-9]+|Grand total)[[:blank:]]*$/d' file 
+1

Ich denke, du bist einer jener Menschen, die Code lesen, wie Sie Ihre gelesen haben Muttersprache. Sehr talentierter Programmierer, 5 Sterne! –

+0

Ich hoffe nicht seit [meine Muttersprache] (https://en.wikipedia.org/wiki/Scots_language) gesprochen wird, nicht geschrieben (wenn es geschrieben wird, ist dies mit phonetischer Schreibweise gemacht, was es sehr variabel und schwer zu lesen macht!): -). –

1

Sie tun können:

grep -v -P "^(Subtotal Group \d+|Grand total)[,\s]*$" inputfile > outputfile 

Herausgegeben per Kommentar. Second Edit: angepasst an neue Spezifikationen

+0

Es gibt keine Notwendigkeit, 'cat' und' | 'zu verwenden, einfach verwenden:' grep -v ",,, $" infile> outfile' – user3439894

0

Die Frage ist nicht ganz klar, ob das Ziel ist, die Gesamt-/Zwischensummenzeilen zu behalten, oder ob sie entfernt werden sollten.

Es ist auch nicht klar, ob die "# *" - Kommentare ein tatsächlicher Teil der Eingabedatei sind oder nur beschreibend sind.

Glücklicherweise sind diese beiden kleinen Details. Das ist ziemlich einfach zu tun mit perl:

$ perl -n -e 'print if /^(Subtotal|Grand Total),(,| |#.*)*/' inputfile 
Subtotal,,,      #This is unuseful --> To be removed 
Subtotal,,,      #This is unuseful --> To be removed 
Subtotal,,,125.40    #This is a good line 
Subtotal,,,      #This is unuseful --> To be removed 
Grand Total,,,     #This is unuseful --> To be removed 
Grand Total,,,125.40   #This is a good line 

Dies vorausgesetzt, dass Sie die gesamte und die Zwischensummenzeilen halten möchten, und entfernen Sie alle anderen Linien.

es in die andere Richtung tun um, die insgesamt/Wert Ihrer Linien zu entfernen, und die anderen zu halten, ersetzen Sie das Stichwort if mit unless.

Dies auch ignoriert alle zusätzlichen Leerzeichen
perl -n -e 'print if /^(Subtotal|Grand Total),(,|)*/' inputfile 

:

Und wenn die Kommentare selbst nicht tatsächlich in der Eingabedatei sind, muss das Muster nur leicht verändert werden. Wenn Sie Leerzeichen signifikant sein wollen, wird dies:

perl -n -e 'print if /^(Subtotal|Grand Total),(,)*/' inputfile 

Wie ich schon sagte, auch wenn Ihre Frage nicht 100% klar ist, sind die unklaren Teile nur Kleinigkeiten. perl wird leicht jede Möglichkeit behandeln.

Wie im Beispiel gezeigt, druckt perl das bearbeitete inputfile auf Standardausgabe. Um inputfile durch den bearbeiteten Inhalt zu ersetzen, fügen Sie einfach die Option -i zum Befehl hinzu (vor der -e Option).

1

Wenn Ihre good Linien enden immer mit einer Nummer und Ihre Any Text Linien nicht, könnten Sie verwenden:

sed -n '/^.*[0-9]$/p' file 

Wo -n Druck von Musterraum unterdrücken, und Sie werden nur dann ausgegeben, Zeilen, die mit [0-9] enden. Angesichts Ihrer Beispieldatei ist die Ausgabe:

Subtotal           2123.82 
Total            625.80 
Any Word           9999.99 
0

Und der Versuch einer awk Lösung ...

awk -F, '{for(i=2;i<=NF;i++){if($i~/[0-9.-]+/){print $0;next}}}' falzone 
Subtotal,,,125.40    
Grand Total,,,125.40    
Any other text,,,9999.99 

Oder an der Nicht-csv-Version suchen:

grep [0-9.-] falzone2 
Subtotal           2123.82 
Total            625.80 
Any Word           9999.99 
Verwandte Themen