Mescola due file di testo paralleli


9

Ho due corpora paralleli allineati a frase (file di testo) con circa 50 milioni di parole. (dal corpus Europarl -> traduzione parallela di documenti legali). Ora vorrei mescolare le linee dei due file, ma entrambi allo stesso modo. Volevo avvicinarmi a questo usando gshuf (sono su un Mac) usando un'unica fonte casuale.

gshuf --random-source /path/to/some/random/data file1
gshuf --random-source /path/to/some/random/data file2

Ma ho ricevuto il messaggio di errore end of file, perché a quanto pare il seme casuale deve contenere tutte le parole contenute nel file da ordinare. È vero? Se sì, come dovrei creare un seme casuale adatto alle mie esigenze? Se no, in quale altro modo potrei randomizzare i file in parallelo? Ho pensato di incollarli insieme, randomizzare e poi dividere di nuovo. Tuttavia, questo sembra brutto dal momento che avrei bisogno di trovare prima un delimitatore che non si verifica nei file.


1
Hai ricevuto quell'errore perché il tuo file casuale non contiene abbastanza byte ... Vedi random sources. Per quanto riguarda paste, potresti usare come delimitatore un carattere ASCII basso che è improbabile che si verifichi nei tuoi file (come \x02, \x03...).
don_crissti,

Va bene, qualunque cosa io voglia randomizzare, se uso / dev / urandom, dovrei essere a posto, giusto? Il delimitatore di pasta è un buon consiglio, grazie!
conipo,

Risposte:


10

Non so se esiste un metodo più elegante ma questo funziona per me:

mkfifo onerandom tworandom threerandom
tee onerandom tworandom threerandom < /dev/urandom > /dev/null &
shuf --random-source=onerandom onefile > onefile.shuf &
shuf --random-source=tworandom twofile > twofile.shuf &
shuf --random-source=threerandom threefile > threefile.shuf &
wait

Risultato:

$ head -n 3 *.shuf
==> onefile.shuf <==
24532 one
47259 one
58678 one

==> threefile.shuf <==
24532 three
47259 three
58678 three

==> twofile.shuf <==
24532 two
47259 two
58678 two

Ma i file devono avere lo stesso numero esatto di righe.


La documentazione GNU Coreutils fornisce anche una buona soluzione per la casualità ripetuta usando opensslcome generatore casuale seminato:

https://www.gnu.org/software/coreutils/manual/html_node/Random-sources.html#Random-sources

get_seeded_random()
{
  seed="$1"
  openssl enc -aes-256-ctr -pass pass:"$seed" -nosalt \
    </dev/zero 2>/dev/null
}

shuf -i1-100 --random-source=<(get_seeded_random 42)

Tuttavia, considera l'utilizzo di un seme migliore di "42", a meno che tu non voglia che qualcun altro sia in grado di riprodurre anche il "tuo" risultato casuale.


Funziona come un fascino. Ti dispiacerebbe spiegare i passi che hai fatto? Il comando tee assicura che lo stesso numero casuale sia memorizzato in tutte e tre le pipe, giusto? Perché è necessario anche l'output su / dev / null? Ed è automaticamente garantito che ci siano abbastanza byte e che l' end of fileerrore non si verifichi?
conipo,

Il /dev/nullperché teestampa anche a stdout. Potrebbe usare > threerandominvece ma è più difficile da scrivere. Le pipe nominate produrranno tutti i dati casuali necessari, quindi non devi sapere in anticipo di quanto avrai bisogno.
frostschutz,

Ok, e perché non può essere solo una pipe che usi come sorgente casuale per tutti e 3 i riordini uno dopo l'altro?
conipo,

2
Non è possibile leggere gli stessi dati tre volte da una pipe. Devi multiplexare in qualche modo ed è quello che teefa ...
Frostschutz,
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.