¿Cómo puedo eliminar todas las líneas en inglés de un archivo de texto?

11

Tengo este archivo de texto:

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

y me gustaría analizarlo para que solo queden las líneas que no están en inglés

¿es posible?

Deele Ma
fuente
3
¿Puede suponer con seguridad que siempre habrá el mismo número de líneas en cada idioma? Si hay dos líneas alemanas, ¿siempre habrá dos líneas inglesas, etc.?
terdon

Respuestas:

13

Hay un camino difícil y mucho más fácil. La forma difícil es utilizar el análisis de lenguaje natural para dar una probabilidad de que una línea determinada esté en inglés y descartar dichas líneas.

La forma más fácil es tomar una lista de palabras de detención en inglés y eliminar líneas que contienen elementos de esa lista. Si desea disminuir la posibilidad de categorizar erróneamente una línea, también puede buscar la presencia de palabras de detención alemanas en las líneas que no puede rechazar para verificar que probablemente sean alemanas.

Aquí hay un script muy rápido y sucio para usar la lista de palabras de parada vinculadas para hacer el filtrado:

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

y la salida:

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, 

Una versión un poco más completa debería ignorar varios signos de puntuación, ,.pero no el apóstrofe 'en inglés, dentro de una palabra. Se podría obtener una precisión aún mayor buscando puntos de código que nunca ocurran en inglés (por ejemplo «ßü) pero que se dejan como ejercicio para el lector.

msw
fuente
Muy buen enfoque. Mucho mejor que mi enfoque de
pirateo
Danke (el uso de palabras de detención como diagnóstico de un idioma provino de una parte de mi mente que no sabía que estaba allí)
msw
5

En su muestra, esto funcionaría:

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

Detalles

  • RS=. Establece el separador de registros . Un valor vacío es un caso especial que significa que un registro es un párrafo (secuencia de líneas delimitadas por líneas vacías).
  • -F '\n': establece el separador de campo (los campos en cada registro son líneas).
  • OFS='\n': establece el separador de campo de salida.

Para cada registro (párrafo):

  • NF=1+NF/2(o NF=2(las primeras 2 líneas) + (NF-2)/2(la mitad de las líneas restantes)): cambie el número de campos para excluir los ingleses.
  • printf "%s", $0 RT: imprime el registro seguido del terminador del registro (para restaurar la misma cantidad de espacio entre párrafos). Para ver qué está haciendo el código anterior, es útil si agrega algunas declaraciones de impresión en la mezcla. Algo como esto:

Eso supone finales de línea Unix. Si el archivo está en formato MSDOS como es común con los archivos de subtítulos, debe preprocesarlo con d2uo dos2unix.

Stéphane Chazelas
fuente
Esto supone que las líneas en inglés siempre están en la 3ª o 4ª posición, ¿verdad?
slm
2
@slm. No, esa mitad de las líneas son inglesas.
Stéphane Chazelas
Mirando un poco más, esto divide las líneas en registros. Luego busca dentro de cada registro el número de campos (NF). Un NF es una línea en este caso, ¿verdad? Todavía no entiendo lo que estás haciendo con el NF-=NF/2-1bit. ¿Está calculando por ejemplo NF=4para el primer registro, 714. Para que pueda obtener los valores NF=4y NF/2-1=1, a continuación, restando la 1de la NFdejándole con 3? Luego imprime los primeros 3"campos" del registro y, por lo tanto, suelta la cuarta línea.
slm
3

La pieza clave para este tipo de enfoque es tener acceso a una buena base de datos de palabras en inglés. Existe este archivo en mi sistema, /usr/share/dict/wordsque tiene muchas palabras, pero en su lugar podrían usarse otras fuentes.

Acercarse

Mi enfoque general sería usarlo grepasí:

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

Donde está su salida de ejemplo sample.txt.

En mis pruebas limitadas, el tamaño del wordsdiccionario parecía empantanarse grep. Mi versión tiene más de 400k líneas. Entonces comencé a hacer algo como esto para dividirlo un poco:

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

Ejecuciones de muestra (10k)

Luego, ejecute su archivo usando las primeras 10k palabras del "diccionario".

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

NOTA: Este enfoque se ejecutó en ~ 1.5 segundos, en mi computadora portátil i5.

Parece ser un enfoque viable. Sin embargo, cuando lo incrementé hasta las 100 mil líneas, comenzó a tomar mucho tiempo, lo aborté antes de que terminara, para que pudiera dividir el wordsdiccionario en varios archivos.

NOTA: Cuando retrocedí a 50k líneas, tardé 32 segundos.

Bucear más profundo (50k líneas)

Cuando comencé a expandir el diccionario hasta 50k, me encontré con el problema que temía, la superposición entre los idiomas.

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

Analizando el problema

Una buena cosa con este enfoque es que puede eliminar -vy ver dónde está la superposición:

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

aufAparentemente, la palabra está en ambos idiomas ... bueno, al menos está en mi wordsarchivo, por lo que este podría ser un enfoque de prueba y error para refinar la lista de palabras según sea necesario.

NOTA: Sabía que era la palabra aufporque la grepcoloreaba de rojo, eso no aparece en la salida anterior debido a la naturaleza limitada de SE 8-).

$ grep auf ~/50000words 
auf
aufait
aufgabe
aufklarung
auftakt
baufrey
Beaufert
beaufet
beaufin
Beauford
Beaufort
beaufort
bechauffeur
slm
fuente
La palabra "auf" existe en el idioma inglés? Eso DEBE ser un error en el archivo de Word. Definitivamente no es así, al menos no autónomo (que debe ser el único camino para analizar aquí) de todos modos
SyntaxError
@syntaxerror: como dije, está en el archivo de la lista de palabras que estaba usando. Estoy analizando de forma independiente. Eso es lo que grep -wf ...hace. Con un mejor suministro de palabras, este enfoque sería más directo. La otra solución (la de Stephane) depende de los datos que se están estructurando y no los mira de manera contextual, aunque el enfoque de msw parece tener mejores piernas para mí.
slm
Asumí que estabas analizando de forma independiente. Sea cual sea, afirmo que si la palabra "auf" es en realidad parte de un idioma Inglés lista de palabras, quiero ver la referencia de diccionario donde se documenta su existencia. Lo más probable es que no encuentres uno ... nunca. Pero como puede ver, una sola palabra puede crear una confusión total en los analizadores de todo tipo.
syntaxerror
@syntaxerror: perdón por la confusión, no estaba en desacuerdo con usted acerca de que "auf" era una palabra real, solo que estaba en el archivo del diccionario que estaba usando. Por cierto, verifiqué dos veces el linaje de ese archivo y proviene de un paquete en mi computadora portátil Fedora 14 llamado palabras.
Obtiene
1

Esto parece un .srtarchivo. Si es así, y si el número de líneas en inglés por subtítulo es siempre el mismo que el número de líneas en alemán, puede usar:

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

Dónde old.srty dónde new.srtestán sus archivos de entrada y salida elegidos.

Submarino alado
fuente