Entfernen Sie Zeilen, die neuer als das angegebene Datum in einer Datei sind

8

Ich bin nicht sicher, wie ich Zeilen löschen kann, die neuer als das angegebene Datum sind. Hier ist ein Ausschnitt aus dem Inhalt einer Datei.

Buildsave.txt

647919 2013/11/30
647946 2013/11/30
647955 2013/12/01
648266 2013/12/03
648267 2013/12/03
648674 2013/12/04

Ich möchte die Zeilen entfernen, die neuer als 2013/12/03 sind und nur noch übrig bleiben

647919 2013/11/30
647946 2013/11/30
647955 2013/12/01

Wie kann das durch Bash gemacht werden?

Jason G.
quelle

Antworten:

4

Wenn Ihr System die GNU-Version des dateBefehls enthält, können Sie damit das Datumsfeld (nach dem Entfernen des Trailing <br>, falls vorhanden) in Sekunden seit der Epoche konvertieren und direkt mit dem Stichtag im gleichen Format vergleichen, z. B. in Bash

testsecs=$(date +%s --date="2013/12/03")
while IFS= read -r line; do
  read -r x d <<< "$line" 
  if (( $(date +%s --date="${d%<br>}") < $testsecs )); then
    printf '%s\n' "$line"
  fi
done < buildsave.txt

[Beachten Sie, dass hierdurch keine direkte Löschung durchgeführt wird. Sie müssen die Ergebnisse in einer temporären Datei speichern und umbenennen.]

Steeldriver
quelle
Sie, Sir, haben mir Kopfschmerzen erspart. Genau das habe ich gesucht!
Jason G
igitt! Diese Daten sind lexikografisch und chronologisch gleich sortiert. Sie müssen nicht in Ganzzahlen konvertiert und 5 Befehle ausgeführt werden. Erstellen Sie eine temporäre Datei und zwei Pipes pro Zeile!
Stéphane Chazelas
9

Diese Daten sind lexikografisch und chronologisch gleich sortiert, sodass nur ein lexikalischer Vergleich erforderlich ist:

awk '$2 < "2013/12/03"'
Stéphane Chazelas
quelle
2

Ich gehe davon aus, dass das <br>in Ihrer Frage am Ende der dateKolumne etwas Unerwünschtes ist. In jedem Fall kann es leicht entfernt werden, wenn es vorhanden ist. Wenn Sie jedoch zum Hauptteil kommen, können Sie erreichen, was Sie versuchen, mit,

sort -k 2n filename.txt

Mit dem obigen Befehl wird die Ausgabe nun sortiert ausgegeben. Der folgende Befehl sollte nun das geben, wonach Sie suchen.

sort -k 2n filename.txt | awk '/2013\/12\/03/ {exit} {print}' 

Erläuterung

Der Befehl sort sortiert die Datei grundsätzlich nach der zweiten Spalte, die das Datum ist. Deshalb habe ich Ihre Eingabedatei geändert, um den Befehl zu testen, ob er funktioniert, da in der Eingabedatei standardmäßig alle Daten sortiert sind. Danach awkdruckt der Befehl alle Zeilen, bis wir auf eine bestimmte Übereinstimmung stoßen.

Testen

cat filename.txt

647919 2014/01/01
647946 2012/11/30
647955 2011/01/04
648266 2013/12/03
648267 2013/12/03
648674 2013/12/04

Jetzt ist die sort -k 2n filename.txtAusgabe,

647955 2011/01/04
647946 2012/11/30
648266 2013/12/03
648267 2013/12/03
648674 2013/12/04
647919 2014/01/01

Jetzt sind wir zufrieden, dass die Datei in der zweiten Spalte sortiert ist. Um nun Werte bis zu einem bestimmten Datum auszuwählen ,

sort -k 2n filename.txt | awk '/2013\/12\/03/ {exit} {print}' 

Im obigen Beispiel erhalte ich alle Werte bis 2013/12/03. Die Ausgabe ist,

647955 2011/01/04
647946 2012/11/30

Nein, das <br>ist Teil meiner Datei

In diesem Fall können wir den Befehl wie folgt leicht anpassen.

awk '{print $1, substr($2, 1, length($2)-4)}' filename.txt | 
sort -k 2n filename.txt | awk '/2013\/12\/03/ {exit} {print}' 

Also entferne ich einfach alle <br>Tags aus der zweiten Spalte und leite dann den oben genannten Befehl weiter.

Verweise

https://unix.stackexchange.com/a/11323/47538

https://unix.stackexchange.com/a/83069/47538

Ramesh
quelle
Danke für deinen Beitrag. Dies funktioniert zwar sehr gut, die Bedingung zum Beenden funktioniert jedoch nicht immer, wenn das bestimmte Datum nicht in der Datei vorhanden ist.
Jason G
Nein, die br-Tags scheinen hinzugefügt zu werden, um das Ding lesbar zu machen. Sie können nicht in der ersten Revision gesehen werden
Braiam
-1

Schnelle und schmutzige Lösung für das eine Datum, das Sie angegeben haben. Löschen Sie einfach alle Zeilen mit sed, die mit Daten übereinstimmen, die nach diesem Datum liegen:

sed -i "" "#[0-9]* 2013/12/0[4-9]#d" testfile.txt
sed -i "" "#[0-9]* 2013/12/[123][0-9]#d" testfile.txt
sed -i "" "#[0-9]* 2014/[0-9][0-9]/[0-3][0-9]#d" testfile.txt

Das -i "" wird direkt in der Datei ersetzt und erstellt kein Backup. Sie können die Testdatei jedoch auch ohne das -i "" durch alle 3 sed-Befehle leiten.

Abhängig von Ihrem System (Linux oder Mac) können Sie das "" nach -i weglassen und manchmal benötigen Sie den Parameter -e für die regulären Ausdrücke. Ich muss versuchen, was für dich funktioniert.

Verwandte Frage mit weiteren Informationen zu sed: /programming/5410757/

toppy
quelle
#ist der Kommentarbefehl in sed, damit diese nichts tun. Verwenden sed '\#patter#d'Sie diese Option, wenn Sie ein anderes RE-Trennzeichen als möchten /. Das [0-9]*Teil ist ohne ^Anker überflüssig . -ewird nur benötigt, wenn Sie mehrere Ausdrücke übergeben möchten. Linux ist ein Kernel, Mac ist eine Computermarke, keiner hat etwas damit zu tun sed. Der Unterschied besteht zwischen GNU sedund FreeBSD sed(das OS / X (wie auf einigen Macs zu finden) geerbt hat).
Stéphane Chazelas