GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Entfernen Sie effizient die letzten beiden Zeilen einer extrem großen Textdatei

Ich habe dies nicht an einer großen Datei ausprobiert, um zu sehen, wie schnell es ist, aber es sollte ziemlich schnell gehen.

So verwenden Sie das Skript, um Zeilen am Ende einer Datei zu entfernen:

./shorten.py 2 large_file.txt

Es sucht bis zum Ende der Datei, überprüft, ob das letzte Zeichen ein Zeilenumbruch ist, liest dann jedes Zeichen nacheinander rückwärts, bis es drei Zeilenumbrüche gefunden hat, und schneidet die Datei direkt nach diesem Punkt ab. Die Änderung wird übernommen.

Bearbeiten: Ich habe unten eine Python 2.4-Version hinzugefügt.

Hier ist eine Version für Python 2.5/2.6:

#!/usr/bin/env python2.5
from __future__ import with_statement
# also tested with Python 2.6

import os, sys

if len(sys.argv) != 3:
    print sys.argv[0] + ": Invalid number of arguments."
    print "Usage: " + sys.argv[0] + " linecount filename"
    print "to remove linecount lines from the end of the file"
    exit(2)

number = int(sys.argv[1])
file = sys.argv[2]
count = 0

with open(file,'r+b') as f:
    f.seek(0, os.SEEK_END)
    end = f.tell()
    while f.tell() > 0:
        f.seek(-1, os.SEEK_CUR)
        char = f.read(1)
        if char != '\n' and f.tell() == end:
            print "No change: file does not end with a newline"
            exit(1)
        if char == '\n':
            count += 1
        if count == number + 1:
            f.truncate()
            print "Removed " + str(number) + " lines from end of file"
            exit(0)
        f.seek(-1, os.SEEK_CUR)

if count < number + 1:
    print "No change: requested removal would leave empty file"
    exit(3)

Hier ist eine Python 3-Version:

#!/usr/bin/env python3.0

import os, sys

if len(sys.argv) != 3:
    print(sys.argv[0] + ": Invalid number of arguments.")
    print ("Usage: " + sys.argv[0] + " linecount filename")
    print ("to remove linecount lines from the end of the file")
    exit(2)

number = int(sys.argv[1])
file = sys.argv[2]
count = 0

with open(file,'r+b', buffering=0) as f:
    f.seek(0, os.SEEK_END)
    end = f.tell()
    while f.tell() > 0:
        f.seek(-1, os.SEEK_CUR)
        print(f.tell())
        char = f.read(1)
        if char != b'\n' and f.tell() == end:
            print ("No change: file does not end with a newline")
            exit(1)
        if char == b'\n':
            count += 1
        if count == number + 1:
            f.truncate()
            print ("Removed " + str(number) + " lines from end of file")
            exit(0)
        f.seek(-1, os.SEEK_CUR)

if count < number + 1:
    print("No change: requested removal would leave empty file")
    exit(3)

Hier ist eine Version von Python 2.4:

#!/usr/bin/env python2.4

import sys

if len(sys.argv) != 3:
    print sys.argv[0] + ": Invalid number of arguments."
    print "Usage: " + sys.argv[0] + " linecount filename"
    print "to remove linecount lines from the end of the file"
    sys.exit(2)

number = int(sys.argv[1])
file = sys.argv[2]
count = 0
SEEK_CUR = 1
SEEK_END = 2

f = open(file,'r+b')
f.seek(0, SEEK_END)
end = f.tell()

while f.tell() > 0:
    f.seek(-1, SEEK_CUR)
    char = f.read(1)
    if char != '\n' and f.tell() == end:
        print "No change: file does not end with a newline"
        f.close()
        sys.exit(1)
    if char == '\n':
        count += 1
    if count == number + 1:
        f.truncate()
        print "Removed " + str(number) + " lines from end of file"
        f.close()
        sys.exit(0)
    f.seek(-1, SEEK_CUR)

if count < number + 1:
    print "No change: requested removal would leave empty file"
    f.close()
    sys.exit(3)

Sie können GNU Head ausprobieren

head -n -2 file

Ich sehe, dass meine Debian Squeeze/testing-Systeme (aber nicht Lenny/stable) einen „truncate“-Befehl als Teil des „coreutils“-Pakets enthalten.

Damit könnte man einfach so etwas machen wie

truncate --size=-160 myfile

um 160 Bytes vom Ende der Datei zu entfernen (natürlich müssen Sie genau herausfinden, wie viele Zeichen Sie entfernen müssen).


Linux
  1. Gemeinsame Linien (Ähnlichkeiten) zweier Textdateien ausgeben (das Gegenteil von Diff)?

  2. Dateiinhalt ohne die erste und letzte Zeile drucken?

  3. Text zwischen zwei bestimmten Zeilen extrahieren?

  4. Wie entferne ich X Bytes vom Ende einer großen Datei, ohne die gesamte Datei zu lesen?

  5. Wie kann ich Wörter zwischen den ersten beiden Instanzen von Text/Muster erhalten?

So fügen Sie Text am Anfang einer Datei in Linux hinzu

5 Möglichkeiten, die Anzahl der Zeilen in einer Datei zu zählen

Cat-Befehl zeigt die Textzeilen nicht an?

Entfernen Sie ungerade oder gerade Zeilen aus einer Textdatei

Wie extrahiert man Text aus einer großen Datei, beginnend mit dem ersten Auftreten einer Zeichenfolge?

Gibt es eine schnelle Möglichkeit, die allerletzte Datei in einem großen TAR zu erhalten?