Come posso eliminare tutte le righe inglesi da un file di testo?


11

Ho questo file di testo:

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 vorrei analizzarlo in modo che rimangano solo le righe non inglesi

È possibile?


3
Puoi presumere che ci sarà sempre lo stesso numero di righe in ogni lingua? Se ci sono due linee tedesche ci saranno sempre anche due linee inglesi ecc.?
terdon

Risposte:


13

C'è un modo difficile e un modo molto più semplice. Il modo difficile è utilizzare l'analisi del linguaggio naturale per dare una probabilità che una determinata riga sia in inglese e scartare tali righe.

Il modo più semplice è quello di prendere un elenco di parole di stop inglesi ed eliminare le righe che contengono elementi da tale elenco. Se si desidera ridurre la possibilità di classificare erroneamente una linea, è possibile anche cercare la presenza di parole di stop tedesche in righe che non si rifiuta di verificare che siano probabilmente tedesche.

Ecco uno script molto veloce e sporco per utilizzare l'elenco di parole di arresto collegate per eseguire il filtro:

#!/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 l'output:

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 versione leggermente più completa dovrebbe ignorare varie punteggiatura come ,.ma non l'apostrofo inglese 'all'interno di una parola. Una precisione ancora maggiore potrebbe essere ottenuta cercando punti di codice che non si verificano mai in inglese (per esempio «ßü) ma che è lasciato come esercizio per il lettore.


Approccio molto bello. Molto meglio del mio approccio hack e slash Cool
slm

Danke (usare le parole stop come diagnosi di una lingua proveniva da una parte della mia mente che non sapevo fosse lì;)
msw,

5

Nel tuo esempio, questo funzionerebbe:

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

Dettagli

  • RS=. Imposta il separatore record . Un valore vuoto è un caso speciale che indica che un record è un paragrafo (sequenza di righe delimitate da righe vuote).
  • -F '\n': imposta il separatore di campi (i campi in ogni record sono linee).
  • OFS='\n': imposta il separatore del campo di output.

Per ogni record (paragrafo):

  • NF=1+NF/2(o NF=2(le prime 2 righe) + (NF-2)/2(metà delle righe rimanenti)): modifica il numero di campi per escludere quelli inglesi.
  • printf "%s", $0 RT: stampa il record seguito dal terminatore del record (per ripristinare la stessa spaziatura tra i paragrafi). Per vedere cosa sta facendo il codice sopra è utile se aggiungi alcune istruzioni di stampa nel mix. Qualcosa come questo:

Ciò presuppone la fine delle linee Unix. Se il file è in formato MSDOS come è comune con i file dei sottotitoli, è necessario preelaborarlo con d2uo dos2unix.


Ciò presuppone che le linee inglesi siano sempre in terza o quarta posizione, giusto?
slm

2
@slm. No, quella metà delle righe è inglese.
Stéphane Chazelas,

Guardando un po 'di più, questo divide le righe in record. Quindi guardi all'interno di ogni record per il numero di campi (NF). Una NF è una linea in questo caso, giusto? Non riesco ancora a capire cosa stai facendo NF-=NF/2-1. Stai calcolando dire NF=4per il primo record, 714. Quindi ottieni i valori NF=4e NF/2-1=1, quindi, sottraendo il 1dal NFlasciarti con 3? Quindi stampare i primi 3"campi" del record, quindi lasciando cadere la 4a riga?
slm

3

Il pezzo chiave di questo tipo di approccio è l'accesso a un buon database di parole inglesi. C'è questo file sul mio sistema, /usr/share/dict/wordsche contiene molte parole, ma invece potrebbero essere utilizzate altre fonti.

Approccio

Il mio approccio generale sarebbe usare grepcosì:

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

Dove si trova l'output di esempio sample.txt.

Nei miei test limitati la dimensione del wordsdizionario sembrava impantanarsi grep. La mia versione ha 400k + linee al suo interno. Quindi ho iniziato a fare qualcosa del genere per romperlo un po ':

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

Esecuzioni campione (10k)

Esegui il tuo file usando le prime 10k parole del "dizionario".

$ 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: questo approccio ha funzionato in circa 1,5 secondi sul mio laptop i5.

Sembra essere un approccio praticabile. Quando l'ho portato a 100k righe, però, ha iniziato a richiedere molto tempo, l'ho interrotto prima che finisse, in modo da poter suddividere il wordsdizionario in diversi file.

NOTA: quando l'ho eseguito il backup su 50k linee ci sono voluti 32 secondi.

Immersione più profonda (linee 50k)

Quando ho iniziato ad espandere il dizionario fino a 50k mi sono imbattuto nel problema di cui avevo paura, sovrapposizione tra le lingue.

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

Analizzare il problema

Un aspetto positivo di questo approccio è che puoi rimuovere -ve vedere dove si trova la sovrapposizione:

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

aufApparentemente la parola è in entrambe le lingue ... beh almeno è nel mio wordsfile, quindi questo potrebbe essere un po 'un approccio di prova ed errore per affinare l'elenco delle parole secondo necessità.

NOTA: sapevo che era la parola aufperché grepcolorata di rosso, che non compare nell'output sopra a causa della natura limitata di SE Cool.

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

La parola "auf" esiste in lingua inglese? DEVE essere un bug nel file di parole. Sicuramente non lo è, almeno non autonomo (che dovrebbe essere l'unico modo analizzato qui) comunque
syntaxerror

@syntaxerror - come ho già detto è nel file dell'elenco di parole che stavo usando. Sto analizzando autonomo. Questo è quello che grep -wf ...fa. Con una migliore offerta di parole questo approccio sarebbe il più diretto. L'altra soluzione (quella di Stephane) dipende dal fatto che i dati siano strutturati e non li consideri in alcun modo contestuale, ma l'approccio di MSW sembra avere delle gambe migliori per me.
slm

Ho pensato che stavi analizzando autonomamente. Comunque sia, affermo che se la parola "auf" fa davvero parte di un elenco di parole in lingua inglese, voglio vedere il riferimento al dizionario in cui è documentata la sua esistenza. Molto probabilmente, non ne troverai uno ... mai. Ma come puoi vedere, una sola parola può creare totale confusione nei parser di ogni sorta.
syntaxerror,

@syntaxerror - scusami per la confusione, non ero in disaccordo con te sul fatto che "auf" sia una parola vera, solo che si trova nel file del dizionario che stavo usando. Per inciso ho ricontrollato il lignaggio di quel file e proviene da un pacchetto sul mio laptop Fedora 14 chiamato parole. Sorge questo URL come il creatore degli elenchi di parole che sta utilizzando: en.wikipedia.org/wiki/Moby_Project
slm

1

Questo sembra un .srtfile. In tal caso e se il numero di righe inglesi per sottotitolo è sempre uguale al numero di righe tedesche, è possibile utilizzare:

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

Dove old.srte dove new.srtsono i file di input e output scelti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.