Jak mogę usunąć wszystkie angielskie wiersze z pliku tekstowego?

11

Mam ten plik tekstowy:

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,
...

i chciałbym go przeanalizować, aby pozostały tylko linie w języku innym niż angielski

czy to możliwe?

Deele Ma
źródło
3
Czy możesz bezpiecznie założyć, że zawsze będzie taka sama liczba wierszy w każdym języku? Jeśli są dwie linie niemieckie, czy zawsze będą też dwie linie angielskie itp.?
terdon

Odpowiedzi:

13

Jest trudny i znacznie łatwiejszy sposób. Najtrudniejszym sposobem jest użycie parsowania w języku naturalnym, aby dać prawdopodobieństwo, że dana linia jest w języku angielskim i odrzucić takie linie.

Najłatwiejszym sposobem jest pobranie listy angielskich słów stop i usunięcie wierszy zawierających elementy z tej listy. Jeśli chcesz zmniejszyć ryzyko błędnej kategoryzacji wiersza, możesz również poszukać w niemieckiej linii słów stop, których nie odrzucasz, aby sprawdzić, czy prawdopodobnie są niemieckie.

Oto bardzo szybki i nieprzyzwoity skrypt do korzystania z połączonej listy słów stop do wykonania filtrowania:

#!/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]

i wynik:

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, 

Nieco bardziej kompletna wersja powinna ignorować różne znaki interpunkcyjne, takie jak ,.angielski apostrof, ale nie w 'obrębie słowa. Jeszcze większą dokładność można uzyskać, szukając punktów kodowych, które nigdy nie występują w języku angielskim (na przykład «ßü), ale pozostawia to zadanie czytelnikowi.

msw
źródło
Bardzo fajne podejście. O wiele lepszy niż mój hack and slash podejście 8-)
slm
Danke (używanie słów stop jako diagnozy języka pochodzi z części mojego umysłu, o której nie wiedziałem, że tam jest;)
msw
5

Na twojej próbce to zadziałałoby:

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

Detale

  • RS=. Ustawia separator rekordów . Pusta wartość to szczególny przypadek, który oznacza, że rekord jest akapitem (sekwencja linii oddzielona pustymi liniami).
  • -F '\n': ustawia separator pól ( pola w każdym rekordzie są wierszami).
  • OFS='\n': ustawia separator pól wyjściowych.

Dla każdego rekordu (akapitu):

  • NF=1+NF/2(lub NF=2(pierwsze 2 linie) + (NF-2)/2(połowa pozostałych linii)): zmień liczbę pól, aby wykluczyć te angielskie.
  • printf "%s", $0 RT: drukuje rekord, a następnie terminator rekordu (aby przywrócić taką samą odległość między akapitami). Aby zobaczyć, co robi powyższy kod, pomocne jest dodanie do mieszanki instrukcji drukowania. Coś takiego:

To zakłada zakończenia linii uniksowych. Jeśli plik ma format MSDOS, co jest typowe dla plików z napisami, należy go wstępnie przetworzyć za pomocą d2ulub dos2unix.

Stéphane Chazelas
źródło
Zakłada się, że angielskie linie są zawsze na 3. lub 4. pozycji, prawda?
slm
2
@slm. Nie, ta połowa linii to angielski.
Stéphane Chazelas,
Patrząc nieco więcej, dzieli to linie na rekordy. Następnie sprawdzasz w każdym rekordzie liczbę pól (NF). NF jest w tym przypadku linią, prawda? Nadal nie rozumiem, co robisz z tym NF-=NF/2-1kawałkiem. Czy obliczenie głosu NF=4dla pierwszego rekordu, 714. Więc masz wartości NF=4i NF/2-1=1, a następnie odjęcie 1od NFzostawiając 3? Następnie drukujesz pierwsze 3„pola” rekordu, a zatem upuszczasz czwartą linię?
slm
3

Kluczem do tego typu podejścia jest dostęp do dobrej bazy danych angielskich słów. W moim systemie jest ten plik, /usr/share/dict/wordsktóry zawiera wiele słów, ale zamiast tego można użyć innych źródeł.

Podejście

Moje ogólne podejście byłoby greptakie:

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

Gdzie jest twój przykładowy wynik sample.txt.

W moich ograniczonych testach rozmiar wordssłownika wydawał się zwalniać grep. Moja wersja ma ponad 400k linii. Więc zacząłem robić coś takiego, żeby trochę to zepsuć:

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

Przykładowe przebiegi (10 tys.)

Uruchom plik, używając pierwszych 10 000 słów z „słownika”.

$ 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,

UWAGA: To podejście zadziałało w ~ 1,5 sekundy na moim laptopie i5.

Wydaje się to realnym podejściem. Kiedy podniosłem go do 100 000 wierszy, zaczęło to jednak długo zajmować. Przerwałem go, zanim się skończyło, aby można było podzielić wordssłownik na kilka plików.

UWAGA: Kiedy cofnąłem go do 50 000 linii, zajęło to 32 sekundy.

Nurkowanie głębiej (50 tys. Linii)

Kiedy zacząłem rozszerzać słownik do 50 000, natknąłem się na problem, którego się obawiałem, nakładający się na siebie języki.

$ 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,

Analizując problem

Jedną dobrą rzeczą w tym podejściu jest to, że możesz usunąć -vi zobaczyć, gdzie nakłada się:

$ 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,

Słowo aufjest najwyraźniej w obu językach ... cóż, przynajmniej w moim wordspliku, więc może to być podejście prób i błędów w celu dopracowania listy słów w razie potrzeby.

UWAGA: Wiedziałem, że to słowo, aufponieważ greppokolorowane na czerwono, które nie pojawia się na powyższym wyjściu z powodu ograniczonej natury SE 8-).

$ grep auf ~/50000words 
auf
aufait
aufgabe
aufklarung
auftakt
baufrey
Beaufert
beaufet
beaufin
Beauford
Beaufort
beaufort
bechauffeur
slm
źródło
Słowo „auf” istnieje w języku angielskim? To MUSI być błąd w pliku słowa. Zdecydowanie tak nie jest, przynajmniej nie jest samodzielny (co powinno być tutaj jedynym analizowanym sposobem)
syntaxerror
@syntaxerror - jak już powiedziałem, jest w pliku listy słów, którego używałem. Analizuję samodzielnie. To właśnie grep -wf ...robi. Przy większej liczbie słów takie podejście byłoby bardziej bezpośrednie. Inne rozwiązanie (Stephane'a) zależy od struktury danych i nie patrzy na nie w żaden kontekstowy sposób, ale podejście msw wydaje mi się lepsze.
slm
Przypuszczałem ty zostały parsowania samodzielnie. Niezależnie od tego potwierdzam, że jeśli słowo „auf” jest rzeczywiście częścią listy słów w języku angielskim , chcę zobaczyć odniesienie w słowniku, w którym udokumentowano jego istnienie. Najprawdopodobniej nie znajdziesz ... nigdy. Ale jak widać, jedno proste słowo może wywołać całkowite zamieszanie w parserach wszelkiego rodzaju.
syntaxerror
@syntaxerror - przepraszam za zamieszanie, nie nie zgadzałem się z tobą o tym, że „auf” jest prawdziwym słowem, tylko że tak się dzieje w pliku słownika, którego używałem. Nawiasem mówiąc, dwukrotnie sprawdziłem rodowód tego pliku i pochodzi on z pakietu na moim laptopie Fedory 14 o nazwie słowa. Źródło tego adresu URL jest inicjatorem używanych przez niego list słów: en.wikipedia.org/wiki/Moby_Project
slm
1

To wygląda jak .srtplik. Jeśli tak jest, a liczba angielskich wierszy w podtytule jest zawsze taka sama jak liczba niemieckich wierszy, możesz użyć:

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

Gdzie old.srti gdzie new.srtsą wybrane pliki wejściowe i wyjściowe.

wingedsubmariner
źródło