Як я можу видалити всі англійські рядки з текстового файлу?


11

У мене є цей текстовий файл:

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

і хотіли б його розібрати, щоб залишилися лише не англійські лінії

це можливо?


3
Чи можете ви сміливо припускати, що в кожній мові завжди буде однакова кількість рядків? Якщо є дві німецькі лінії, чи завжди будуть також дві англійські лінії тощо?
terdon

Відповіді:


13

Є складний шлях і набагато простіший спосіб. Важким способом є використання природного розбору мови, щоб дати вірогідність того, що даний рядок є англійською мовою, і відкинути такі рядки.

Найпростіший спосіб - взяти список англійських стоп-слів та видалити рядки, що містять елементи із цього списку. Якщо ви хочете зменшити ймовірність неправильної класифікації рядка, ви також можете шукати наявність німецьких стоп-слів у рядках, які ви не можете відхилити, щоб перевірити, чи вони, ймовірно, німецькі.

Ось дуже швидкий і брудний сценарій, щоб використовувати пов'язаний список зупинок для фільтрації:

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

і вихід:

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, 

Трохи більш повна версія повинна ігнорувати різні пунктуації, як, ,.але не англійський апостроф, 'коли в межах слова. Ще більшу точність можна отримати, шукаючи кодові точки, які ніколи не зустрічаються англійською мовою (наприклад «ßü), але це залишається як вправа для читача.


Дуже приємний підхід. Набагато краще, ніж мій хак і слэш підхід 8-)
slm

Danke (використовуючи стоп-слова в якості діагностики мови, виходив з частини розуму, яку я не знав, що там є);
msw

5

На вашому зразку це буде працювати:

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

Деталі

  • RS=. Встановлює роздільник записів . Порожнє значення - це особливий випадок, який означає, що запис є абзацом (послідовність рядків, розділених порожніми рядками).
  • -F '\n': встановлює роздільник поля ( поля у кожному записі - це рядки).
  • OFS='\n': встановлює роздільник вихідного поля.

Для кожного запису (абзацу):

  • NF=1+NF/2(або NF=2(перші два рядки) + (NF-2)/2(половина решти рядків)): змініть кількість полів, щоб виключити англійські.
  • printf "%s", $0 RT: друкує запис, за яким слід термінатор запису (для відновлення однакової відстані між абзацами). Щоб побачити, що робить вищезазначений код, корисно, якщо додати в суміш деякі заяви про друк. Щось на зразок цього:

Це передбачає закінчення рядків Unix. Якщо файл у форматі MSDOS, як це звичайно для файлів субтитрів, потрібно попередньо обробити його з d2uабо dos2unix.


Це передбачає, що англійські лінії завжди знаходяться на 3-й чи 4-й позиціях, правда?
slm

2
@slm. Ні, що половина рядків англійською мовою.
Стефан Шазелас

Поглянувши трохи більше, це розбиває рядки на записи. Потім ви шукаєте в кожному записі кількість полів (NF). NF - це лінія в цьому випадку, правда? Я досі не розумію, що ти робиш зі NF-=NF/2-1шматочком. Чи обчислюєте ви скажімо NF=4для першого запису, 714. Отже, ви отримуєте значення NF=4і NF/2-1=1, а потім віднімаєте 1від, NFзалишаючи вас 3? Тоді друкуємо перші 3"поля" запису, отже, випадаючи 4-й рядок?
slm

3

Ключовим елементом такого типу підходу є доступ до гарної бази англійських слів. У моїй системі є цей файл, /usr/share/dict/wordsякий містить багато слів, але натомість можна використовувати інші джерела.

Підхід

Мій загальний підхід полягає в тому, щоб використовувати grepтак:

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

Там, де знаходиться ваш вихідний приклад sample.txt.

У моєму обмеженому тестуванні розмір wordsсловника, здавалося, занепав grep. Моя версія має 400k + рядків у ній. Тому я почав робити щось подібне, щоб трохи розбити це:

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

Пробірки зразків (10 к)

Запустіть свій файл, використовуючи перші 10 к слів із "словника".

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

ПРИМІТКА. Цей підхід працював за ~ 1,5 секунди на моєму ноутбуці i5.

Це здається життєздатним підходом. Коли я зіткнувся з ним до 100k рядків, це почало тривати багато часу, я перервав його, перш ніж він закінчився, щоб ви могли розбити wordsсловник на кілька файлів.

ПРИМІТКА. Коли я повернув її до 50k рядків, це зайняло 32 секунди.

Дайвінг глибше (50k лінії)

Коли я почав розширювати словник до 50 тис., Я зіткнувся з проблемою, якої я боявся, перетинаючись між мовами.

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

Аналіз проблеми

Хороша річ при такому підході - ви можете видалити -vта побачити, де перекриття:

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

Слово auf, мабуть, на обох мовах ... ну, принаймні, воно є в моєму wordsфайлі, тож це може бути дещо пробним і помилковим підходом, щоб уточнити список слів за потребою.

ПРИМІТКА: Я знав, що це слово, aufтому що grepзабарвив його в червоний колір, що не відображається у вищенаведеному висновку через обмежений характер SE 8-).

$ grep auf ~/50000words 
auf
aufait
aufgabe
aufklarung
auftakt
baufrey
Beaufert
beaufet
beaufin
Beauford
Beaufort
beaufort
bechauffeur

Слово "auf" існує в англійській мові? Це ОБОВ'ЯЗКОВО бути помилкою у файлі слова. Це, безумовно, немає, принаймні, не окремо (це повинен бути єдиний спосіб проаналізований тут)
syntaxerror

@syntaxerror - як я вже сказав, що це у файлі списку слів, який я використовував. Я розбираю самостійно. Ось що grep -wf ...робить. При кращому забезпеченні слів цей підхід був би більш прямим. Інше рішення (Стефанове) залежить від структури даних і не дивиться на нього в будь-якому контекстуальному плані, але підхід MSW, здається, має кращі результати для мене.
slm

Я припустив , що ви були розбір автономні. Як би там не було, я стверджую, що якщо слово "auf" дійсно є частиною англомовного списку слів, я хочу побачити посилання на словник, де підтверджено його існування. Швидше за все, ви її не знайдете ... ніколи. Але, як бачите, одне просте слово може створити тотальну плутанину у різного роду аналізаторів.
синтаксис-помилка

@syntaxerror - вибачте за плутанину, я не погоджувався з вами щодо того, що "auf" є фактичним словом, просто так воно трапляється у файлі словника, який я використовував. Між іншим, я двічі перевірив походження цього файлу, і він походить від пакета на моєму ноутбуці Fedora 14 під назвою слова. Ця URL-адреса є джерелом списків слів, які вона використовує: en.wikipedia.org/wiki/Moby_Project
slm

1

Це схоже на .srtфайл. Якщо це так, і якщо кількість англійських рядків на підзаголовок завжди те саме, що кількість німецьких рядків, то ви можете використовувати:

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

Де old.srtі new.srtякі обрані вами вхідні та вихідні файли.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.