2010-01-03 7 views
5

Ich habe eine Textdatei (richtiger, “ deutschen Stil “ CSV-Datei, dh Semikolon getrennt, Komma), die ein Datum und den Wert hat einer Messung auf jeder Linie.
Es gibt Abschnitte mit fehlerhaften Werten, die ich vor weiteren Arbeiten entfernen möchte. Ich möchte diese Schnitte in einem Skript speichern, damit meine Korrekturen dokumentiert werden und ich diese Korrekturen ggf. wiederholen kann.Entfernen Sie Linien, die zwischen bestimmten Mustern aus einer Datei sind (mit Unix-Tools)

die Linien wie folgt aussehen:

28.01.2005 14:48:38;5,166 
28.01.2005 14:50:38;2,916 
28.01.2005 14:52:38;0,000 
28.01.2005 14:54:38;0,000 
(long stretch of values that should be removed; could also be something else beside 0) 
01.02.2005 00:11:43;0,000 
01.02.2005 00:13:43;1,333 
01.02.2005 00:15:43;3,250 

Jetzt würde ich Muster beginnen und enden speichern wie eine Liste wie 28.01.2005 14:52:38 + 01.02.2005 00:11:43, und das Skript die Linien schneiden würde diese beginnen/enden Paare passende und alles was zwischen ihnen ist.

Ich denke darüber nach, ein awk-Skript zu hacken, aber vielleicht fehlt mir ein bereits vorhandenes Tool.

Antwort

16

Werfen Sie einen Blick auf sed:

sed '/start_pat/,/end_pat/d' 

löscht Linien zwischen start_pat10 und end_pat (inklusive).

mehrere solcher Paare zu löschen, können Sie sie mit mehreren -e Optionen kombinieren:

sed -e '/s1/,/e1/d' -e '/s2/,/e2/d' -e '/s3/,/e3/d' ... 
+0

Großartig! Ich wusste, dass ich etwas verpasst habe und hellip; Ich habe immer sed mit einzelnen Mustern verwendet und nie daran erinnert, dass es Bereiche anbietet. –

+0

Außerdem kann ich die Ausdrücke in eine Datei schreiben, wo ich auch Kommentare (mit '#') verwenden kann. Die Befehlszeile lautet dann "sed -f scriptfile outfile". –

-1

Verwendung grep -L (Druck keine passenden Zeilen)

Sorry - haben Sie ohne 0.000 am Ende gerade Linien wollte

+0

grep -L wird nicht passende Dateinamen drucken. grep -v würde nicht übereinstimmende Zeilen drucken, aber das OP scheint nach etwas komplizierter zu sein (mit Bereichen). – mopoke

+0

Ok, ich dachte, sie wollten nur anyting ohne 0.000 am Ende –

+0

Drucken In der Tat, mein Beispiel war ein bisschen irreführend – gibt es andere fehlerhafte Werte neben 0, z. negative. –

0

Erstens warum müssen Sie einen Datensatz halten, was Sie getan haben? Warum nicht eine Sicherungskopie der Originaldatei erstellen oder einen Unterschied zwischen den alten & neuen Dateien machen oder sie unter Quellcodeverwaltung setzen?

Für die tatsächlichen Änderungen empfehle ich die Verwendung von Vim.

Der Befehl Vim :global (abgekürzt als :g) kann verwendet werden: ex-Befehle in Zeilen, die mit einer Regex übereinstimmen. Dies ist in vielerlei Hinsicht leistungsfähiger als awk, da sich die Befehle dann auf Bereiche beziehen können, die sich auf die übereinstimmende Zeile beziehen, und Sie haben die volle Textverarbeitungsleistung von Vim zur Verfügung.

Zum Beispiel wird dies tun, etwas in der Nähe zu dem, was Sie wollen (nicht getestet, so caveat emptor):

:g!/^\d\d\.\d\d\.\d\d\d\d/ -1 write tmp.txt >> | delete 

Dies entspricht Zeilen, die mit einem Datum nicht gestartet werden (die ! negiert das Spiel), Appends Die vorherige Zeile der Datei tmp.txt löscht die aktuelle Zeile.

Sie werden wahrscheinlich mit doppelten Zeilen in tmp.txt enden, aber sie können entfernt werden, indem Sie die Datei über uniq ausführen.

+0

Ich möchte kurze Notizen über die Aufzeichnungen, die ich rausgeworfen habe und warum. Ich werde nicht sehr häufig mit diesen Daten arbeiten, und ich weiß, dass ich vergessen könnte, was ich getan habe. Auch jemand anderes muss verstehen und reproduzieren, was ich getan habe. Leider löst Ihr vi/ex-Beispiel mein Problem nicht wirklich, da alle Zeilen mit einem Datum beginnen. Aber ich verstehe die Richtung, auf die Sie zeigen. –

0

Sie auch awk verwenden

awk '/start/,/end/' file 
+1

Irgendwo wurde erwähnt, dass awk geeignet ist, wenn Daten im Spaltenformat dargestellt werden. Ist das korrekt. Könntest du bitte erklären, ob awk besser ist als diese spezielle Aufgabe? –

0

ich ernsthaft die Grundlagen von Perl-Lernen (das heißt nicht das OO Zeug) vorschlagen würde. Es wird Ihnen in Eimerladungen zurückzahlen.

Es ist schnell und einfach, ein wenig Perl zu schreiben, um dies zu tun (und viele andere solche Aufgaben), sobald Sie die Grundlagen verstanden haben, die, wenn Sie awk, sed, grep usw. gewohnt sind, ziemlich einfach sind.

Sie müssen sich nicht daran erinnern, wie Sie viele verschiedene Tools verwenden und wo Sie zuvor mehrere Tools verwendet hätten, um ein Problem zu lösen. Sie können einfach ein einzelnes Perl-Skript verwenden (normalerweise schneller ausführen).

Und Perl ist jetzt auf praktisch jeder Unix/Linux Distribution installiert.

(das sed ist aber ordentlich :-)