Como posso excluir todas as linhas em inglês de um arquivo de texto?

11

Eu tenho este arquivo 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,
...

e gostaria de analisá-lo para que apenas as linhas não inglesas permaneçam

isso é possível?

    
por Deele Ma 31.08.2013 / 14:38

4 respostas

13

Existe um caminho difícil e muito mais fácil. A maneira difícil é usar a análise de linguagem natural para dar uma probabilidade de que uma determinada linha esteja em inglês e descartar essas linhas.

A maneira mais fácil é pegar uma lista de palavras de parada em inglês e excluir linhas que contenham elementos de essa lista. Se você quisesse diminuir a chance de categorizar erroneamente uma linha, também poderia procurar a presença de palavras de interrupção em alemão que você não possa rejeitar para verificar se elas são provavelmente em alemão.

Aqui está um script muito rápido e sujo para usar a lista de palavras irrelevantes vinculadas para fazer a filtragem:

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

e a saída:

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, 

Uma versão um pouco mais completa deve ignorar várias pontuações como ,. , mas não o apóstrofo em inglês ' quando dentro de uma palavra. Uma precisão ainda maior poderia ser obtida procurando pontos de código que nunca ocorrem em inglês (por exemplo, «ßü ), mas isso é deixado como um exercício para o leitor.

    
por 31.08.2013 / 14:51
5

Na sua amostra, isso funcionaria:

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

Detalhes

  • %código%. Define o separador de registro . Um valor vazio é um caso especial que significa que um registro é um parágrafo (sequência de linhas delimitada por linhas vazias).
  • RS= : define o separador de campos (os campos em cada registro são linhas).
  • -F '\n' : define o separador do campo de saída.

Para cada registro (parágrafo):

  • OFS='\n' (ou NF=1+NF/2 (as primeiras 2 linhas) NF=2 (metade das linhas restantes)): altera o número de campos para excluir os ingleses.
  • + (NF-2)/2 : imprime o registro seguido pelo terminador de registro (para restaurar a mesma quantidade de espaçamento entre parágrafos). Para ver o que o código acima está fazendo, é útil se você adicionar algumas instruções de impressão à mistura. Algo parecido com isto:

Isso pressupõe finais de linha do Unix. Se o arquivo estiver no formato MSDOS, como é comum nos arquivos de legenda, você precisará pré-processá-lo com printf "%s", $0 RT ou d2u .

    
por 31.08.2013 / 15:14
3

A chave para esse tipo de abordagem é ter acesso a um bom banco de dados de palavras em inglês. Existe esse arquivo no meu sistema, /usr/share/dict/words , que tem muitas palavras, mas outras fontes poderiam ser usadas.

Abordagem

Minha abordagem geral seria usar grep da seguinte forma:

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

Onde a saída do seu exemplo está em sample.txt .

Em meus testes limitados, o tamanho do dicionário words pareceu atrapalhar grep . Minha versão tem mais de 400k linhas. Então comecei a fazer algo assim para dividir um pouco:

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

Amostra é executada (10k)

Execute o arquivo usando as primeiras 10 mil palavras do "dicionário".

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

OBSERVAÇÃO: Essa abordagem foi executada em ~ 1,5 segundos, no meu laptop i5.

Parece ser uma abordagem viável. Quando aumentei para 100k linhas, comecei a demorar muito, mas abortei antes de terminar, então você poderia dividir o dicionário words em vários arquivos.

OBSERVAÇÃO: Quando eu recuei para 50k linhas, levou 32 segundos.

Mergulho mais profundo (50k linhas)

Quando comecei a expandir o dicionário até 50k, encontrei o problema que eu tinha medo, sobreposição entre os 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,

Analisando o problema

Uma coisa boa com essa abordagem é que você pode remover o -v e ver onde a sobreposição está:

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

A palavra auf aparentemente está em ambos os idiomas ... bem, pelo menos está no meu arquivo words , então isso pode ser uma abordagem de tentativa e erro para refinar a lista de palavras conforme necessário.

OBSERVAÇÃO: Eu sabia que era a palavra auf porque grep coloriu vermelho, que não aparece na saída acima devido à natureza limitada do SE 8-).

$ grep auf ~/50000words 
auf
aufait
aufgabe
aufklarung
auftakt
baufrey
Beaufert
beaufet
beaufin
Beauford
Beaufort
beaufort
bechauffeur
    
por 31.08.2013 / 16:09
1

Isso parece um arquivo .srt . Se for, e se o número de linhas inglesas por legenda é sempre o mesmo que o número de linhas alemãs, então você pode 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

Onde old.srt e new.srt são seus arquivos de entrada e saída escolhidos.

    
por 31.08.2013 / 15:44

Tags