Wie kann ich alle englischen Zeilen aus einer Textdatei löschen?

11

Ich habe diese Textdatei:

714
01:11:22,267 --> 01:11:27,731
Auch wenn noch viele Generationen auf einen Wechsel hoffen,
Even if it takes many generations hoping for a change,

715
01:11:27,732 --> 01:11:31,920
werde ich mein Bestes geben
und hoffe, dass andere das gleiche tun.
I'm giving mine, I'm doing my best
hoping the other will do the same

716
01:11:31,921 --> 01:11:36,278
Wir haben eine harte Arbeit vor uns, 
um den Lauf der Dinge zu ändern. 
it's going to be hard work
for things to turn around.

717
01:11:36,879 --> 01:11:42,881
Wenn man die Zentren künstlicher Besamung, 
die Zuchtlaboratorien und die modernen Kuhställe besichtigt, 
When visiting artificial insemination centers,
the selection center, modern stables,
...

und möchte es analysieren, damit nur die nicht englischen Zeilen bleiben

Ist das möglich?

Deele Ma
quelle
3
Können Sie davon ausgehen, dass in jeder Sprache immer die gleiche Anzahl von Zeilen vorhanden ist? Wenn es zwei deutsche Linien gibt, gibt es dann immer auch zwei englische Linien usw.?
Terdon

Antworten:

13

Es gibt einen schwierigen und einen viel einfacheren Weg. Der schwierige Weg besteht darin, das Parsen in natürlicher Sprache zu verwenden, um die Wahrscheinlichkeit zu bestimmen, dass eine bestimmte Zeile auf Englisch ist, und solche Zeilen zu verwerfen.

Der einfachere Weg ist, eine Liste mit englischen Stoppwörtern zu erstellen und Zeilen zu löschen, die Elemente aus dieser Liste enthalten. Wenn Sie die Wahrscheinlichkeit einer falschen Kategorisierung einer Zeile verringern möchten, können Sie auch nach deutschen Stoppwörtern in Zeilen suchen, die Sie nicht ablehnen, um zu überprüfen, ob sie wahrscheinlich deutsch sind.

Hier ist ein sehr schnelles und schmutziges Skript, mit dem die verknüpfte Stoppwortliste zum Filtern verwendet wird:

#!/usr/bin/python
english_stop = set()
with open('english-stop-words.txt') as estop:
    for line in estop:
        bar = line.find('|')
        if bar > -1:
            line = line[0:bar]
        line = line.strip()
        if line:
            english_stop.add(line)

with open('mixed-german.txt') as mixg:
    for line in mixg:
        for word in line.lower().split():
            if word in english_stop:
                break
        else:
            print line[:-1]

und die Ausgabe:

714
01:11:22,267 --> 01:11:27,731
Auch wenn noch viele Generationen auf einen Wechsel hoffen,

715
01:11:27,732 --> 01:11:31,920
werde ich mein Bestes geben
und hoffe, dass andere das gleiche tun.

716
01:11:31,921 --> 01:11:36,278
Wir haben eine harte Arbeit vor uns, 
um den Lauf der Dinge zu ändern. 

717
01:11:36,879 --> 01:11:42,881
Wenn man die Zentren künstlicher Besamung, 
die Zuchtlaboratorien und die modernen Kuhställe besichtigt, 

Eine etwas vollständigere Version sollte verschiedene Satzzeichen wie ,.den englischen Apostroph ignorieren, 'wenn sie sich innerhalb eines Wortes befinden. Eine noch größere Genauigkeit könnte erzielt werden, wenn nach Codepunkten gesucht wird, die beispielsweise auf Englisch nie vorkommen «ßü, die dem Leser jedoch als Übung überlassen bleiben.

msw
quelle
Sehr schöner Ansatz. Viel besser als mein Hack-and-Slash-Ansatz 8-)
slm
Danke (die Verwendung von Stoppwörtern als Diagnose einer Sprache kam aus einem Teil meines Geistes, von dem ich nicht wusste, dass er da war;)
msw
5

Bei Ihrer Stichprobe würde dies funktionieren:

awk -v RS= -F '\n' -v OFS='\n' '{NF=NF/2+1;printf "%s", $0 RT}'

Einzelheiten

  • RS=. Legt das Datensatztrennzeichen fest . Ein leerer Wert ist ein Sonderfall, dh ein Datensatz ist ein Absatz (Folge von Zeilen, die durch leere Zeilen begrenzt sind).
  • -F '\n': Legt das Feldtrennzeichen fest ( Felder in jedem Datensatz sind Zeilen).
  • OFS='\n': Legt das Trennzeichen für das Ausgabefeld fest.

Für jeden Datensatz (Absatz):

  • NF=1+NF/2(oder NF=2(die ersten 2 Zeilen) + (NF-2)/2(die Hälfte der verbleibenden Zeilen)): Ändern Sie die Anzahl der Felder, um die englischen auszuschließen.
  • printf "%s", $0 RT: Druckt den Datensatz, gefolgt vom Datensatzabschlusszeichen (um den gleichen Abstand zwischen den Absätzen wiederherzustellen). Um zu sehen, was der obige Code tut, ist es hilfreich, wenn Sie dem Mix einige print-Anweisungen hinzufügen. Etwas wie das:

Dies setzt Unix-Zeilenenden voraus. Wenn die Datei im MSDOS-Format vorliegt, wie es bei Untertiteldateien üblich ist, müssen Sie sie mit d2uoder vorverarbeiten dos2unix.

Stéphane Chazelas
quelle
Dies setzt voraus, dass sich die englischen Linien immer an der 3. oder 4. Position befinden, oder?
slm
2
@slm. Nein, die Hälfte der Zeilen ist englisch.
Stéphane Chazelas
Wenn man ein bisschen mehr aussieht, werden die Zeilen in Rekorde aufgeteilt. Anschließend suchen Sie in jedem Datensatz nach der Anzahl der Felder (NF). Eine NF ist in diesem Fall eine Linie, oder? Ich verstehe immer noch nicht, was du mit dem NF-=NF/2-1Stück machst . Berechnen Sie etwa NF=4für den ersten Datensatz, 714. Sie erhalten also die Werte NF=4und NF/2-1=1und subtrahieren dann die Werte 1von dem, mit NFdem Sie verlassen haben 3? Dann die ersten 3"Felder" des Datensatzes drucken und damit die 4. Zeile löschen?
slm
3

Das Schlüsselelement für diese Art von Ansatz ist der Zugriff auf eine gute Datenbank mit englischen Wörtern. Es gibt diese Datei auf meinem System, /usr/share/dict/wordsdie viele Wörter enthält, aber andere Quellen könnten stattdessen verwendet werden.

Ansatz

Mein allgemeiner Ansatz wäre, grepwie folgt zu verwenden:

$ grep -vwf /usr/share/dict/words sample.txt

Wo sich Ihre Beispielausgabe befindet sample.txt.

In meinen begrenzten Tests wordsschien die Größe des Wörterbuchs ins Stocken zu geraten grep. Meine Version enthält mehr als 400.000 Zeilen. Also habe ich so etwas gemacht, um es ein bisschen aufzubrechen:

$ head -10000 /usr/share/dict/words > ~/10000words

Probeläufe (10k)

Führen Sie Ihre Datei mit den ersten 10.000 Wörtern aus dem "Wörterbuch" durch.

$ grep -vwf ~/10000words sample.txt
714
01:11:22,267 --> 01:11:27,731
Auch wenn noch viele Generationen auf einen Wechsel hoffen,

715
01:11:27,732 --> 01:11:31,920
werde ich mein Bestes geben
und hoffe, dass andere das gleiche tun.
I'm giving mine, I'm doing my best
hoping the other will do the same

716
01:11:31,921 --> 01:11:36,278
Wir haben eine harte Arbeit vor uns, 
um den Lauf der Dinge zu ändern. 
it's going to be hard work
for things to turn around.

717
01:11:36,879 --> 01:11:42,881
Wenn man die Zentren künstlicher Besamung, 
die Zuchtlaboratorien und die modernen Kuhställe besichtigt, 
When visiting artificial insemination centers,
the selection center, modern stables,

HINWEIS: Dieser Ansatz lief auf meinem i5-Laptop in ca. 1,5 Sekunden.

Es scheint ein praktikabler Ansatz zu sein. Als ich es auf 100.000 Zeilen anstieß, dauerte es allerdings lange. Ich habe es abgebrochen, bevor es fertig war, sodass Sie das wordsWörterbuch in mehrere Dateien aufteilen konnten.

HINWEIS: Als ich es auf 50.000 Zeilen zurückgesetzt habe, dauerte es 32 Sekunden.

Tiefer tauchen (50k Linien)

Als ich anfing, das Wörterbuch auf 50.000 zu erweitern, stieß ich auf das Problem, vor dem ich Angst hatte, Überschneidungen zwischen den Sprachen.

$ grep -vwf ~/50000words sample.txt
714
01:11:22,267 --> 01:11:27,731

715
01:11:27,732 --> 01:11:31,920
werde ich mein Bestes geben
und hoffe, dass andere das gleiche tun.
hoping the other will do the same

716
01:11:31,921 --> 01:11:36,278
Wir haben eine harte Arbeit vor uns, 
um den Lauf der Dinge zu ändern. 

717
01:11:36,879 --> 01:11:42,881
Wenn man die Zentren künstlicher Besamung, 
die Zuchtlaboratorien und die modernen Kuhställe besichtigt, 
the selection center, modern stables,

Das Problem analysieren

Eine gute Sache bei diesem Ansatz ist, dass Sie die entfernen -vund sehen können, wo die Überlappung ist:

$ grep -wf ~/50000words sample.txt
Auch wenn noch viele Generationen auf einen Wechsel hoffen,
Even if it takes many generations hoping for a change,
I'm giving mine, I'm doing my best
it's going to be hard work
for things to turn around.
When visiting artificial insemination centers,

Das Wort aufist anscheinend in beiden Sprachen ... zumindest in meiner wordsDatei. Dies könnte also ein Versuch und Irrtum sein, um die Wortliste nach Bedarf zu verfeinern.

HINWEIS: Ich wusste, dass es das Wort war, aufweil grepes rot gefärbt war und in der obigen Ausgabe aufgrund der eingeschränkten Natur von SE 8-) nicht angezeigt wird.

$ grep auf ~/50000words 
auf
aufait
aufgabe
aufklarung
auftakt
baufrey
Beaufert
beaufet
beaufin
Beauford
Beaufort
beaufort
bechauffeur
slm
quelle
Das Wort "auf" existiert in der englischen Sprache? Das muss ein Fehler in der Word-Datei sein. Es ist definitiv nicht, zumindest nicht eigenständig (was hier der einzige Weg sein sollte)
Syntaxfehler
@syntaxerror - wie gesagt, es ist in der Wortlistendatei, die ich verwendet habe. Ich analysiere Standalone. Das grep -wf ...macht der. Mit einer besseren Wortversorgung wäre dieser Ansatz direkter. Die andere Lösung (die von Stephane) hängt von der Struktur der Daten ab und betrachtet sie in keiner kontextuellen Weise. Der Ansatz von msw scheint mir jedoch bessere Beine zu haben.
slm
Ich nehme Sie wurden eigenständige Parsen. Wie auch immer, ich bestätige, dass ich, wenn das Wort "auf" wirklich Teil einer englischsprachigen Wortliste ist, die Wörterbuchreferenz sehen möchte, in der seine Existenz dokumentiert ist. Höchstwahrscheinlich werden Sie nie einen finden. Aber wie Sie sehen können, kann ein einziges Wort bei Parsern aller Art zu völliger Verwirrung führen.
Syntaxfehler
@syntaxerror - Entschuldigung für die Verwirrung, ich war nicht anderer Meinung als Sie darüber, dass "auf" ein tatsächliches Wort ist, nur dass es sich zufällig in der von mir verwendeten Wörterbuchdatei befindet. Übrigens habe ich die Herkunft dieser Datei überprüft und sie stammt aus einem Paket auf meinem Fedora 14-Laptop mit dem Namen words. Es
bezieht
1

Das sieht aus wie eine .srtDatei. Wenn dies der Fall ist und die Anzahl der englischen Zeilen pro Untertitel immer der Anzahl der deutschen Zeilen entspricht, können Sie Folgendes verwenden:

awk 'BEGIN { RS="\r\n\r\n"; FS="\r\n"} {for (i=1;i<=(NF-2)/2+2; i++) print $i "\r"; print "\r"}' old.srt > new.srt

Wo old.srtund new.srtsind Ihre ausgewählten Eingabe- und Ausgabedateien.

wingedsubmariner
quelle