Kocok dua file teks paralel

9

Saya memiliki dua korpora paralel yang disejajarkan dengan kalimat (file teks) dengan sekitar 50 juta kata. (dari Europarl corpus -> terjemahan paralel dokumen hukum). Sekarang saya ingin mengocok kedua file, tetapi keduanya dengan cara yang sama. Saya ingin melakukan pendekatan dengan menggunakan gshuf (saya menggunakan Mac) menggunakan satu sumber acak unik.

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

Tapi saya mendapat pesan kesalahan end of file, karena tampaknya seed acak perlu berisi semua kata yang berisi file yang akan diurutkan. Benarkah? Jika ya, bagaimana cara saya membuat benih acak yang baik untuk kebutuhan saya? Jika tidak, dengan cara apa lagi saya dapat mengacak file secara paralel? Saya berpikir tentang menempelkannya bersama, mengacak dan kemudian membelah lagi. Namun, ini tampak jelek karena saya harus terlebih dahulu menemukan pembatas yang tidak terjadi pada file.

conipo
sumber
1
Anda mendapatkan kesalahan itu karena random_file Anda tidak mengandung cukup byte ... Lihat random sources. Untuk itu paste, Anda dapat menggunakan sebagai pembatas beberapa char ascii rendah yang tidak mungkin terjadi pada file Anda (seperti \x02, \x03...).
don_crissti
Baiklah, apa pun yang saya inginkan untuk diacak, jika saya menggunakan / dev / urandom, saya harus baik-baik saja, bukan? Pembatas pasta adalah tip yang bagus, terima kasih!
conipo

Jawaban:

10

Saya tidak tahu apakah ada metode yang lebih elegan tetapi ini berhasil bagi saya:

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

Hasil:

$ 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

Tetapi file harus memiliki jumlah baris yang sama persis.


Dokumentasi GNU Coreutils juga menyediakan solusi yang bagus untuk keacakan berulang menggunakan opensslsebagai generator acak unggulan:

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)

Namun, pertimbangkan untuk menggunakan benih yang lebih baik daripada "42", kecuali jika Anda ingin orang lain dapat mereproduksi hasil acak "Anda" juga.

frostschutz
sumber
Ini bekerja seperti pesona. Maukah Anda menjelaskan langkah-langkah yang Anda ambil? Perintah tee memastikan bahwa nomor acak yang sama disimpan di ketiga pipa, kan? Mengapa perlu output ke / dev / null juga? Dan apakah secara otomatis memastikan bahwa ada cukup byte dan bahwa end of filekesalahan tidak terjadi?
conipo
Itu /dev/nullkarena teejuga mencetak ke stdout. Bisa digunakan > threerandomsebagai gantinya tetapi lebih sulit untuk skrip. Pipa yang dinamai akan menghasilkan data acak sebanyak yang diperlukan, jadi Anda tidak perlu tahu sebelumnya berapa banyak yang Anda perlukan.
frostschutz
Ok, dan mengapa tidak bisa hanya menjadi satu pipa yang Anda gunakan sebagai sumber acak untuk semua 3 mengocok satu demi satu?
conipo
2
Anda tidak dapat membaca data yang sama tiga kali dari satu pipa. Anda harus multiplex entah bagaimana dan itulah yang tee...
frostschutz