Xáo trộn hai tệp văn bản song song


9

Tôi có hai văn bản song song liên kết câu (tệp văn bản) với khoảng 50 triệu từ. (từ văn bản Europarl -> dịch song song các tài liệu pháp lý). Bây giờ tôi muốn xáo trộn các dòng của hai tệp, nhưng cả hai đều theo cùng một cách. Tôi muốn tiếp cận việc sử dụng gshuf (Tôi trên máy Mac) bằng một nguồn ngẫu nhiên duy nhất.

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

Nhưng tôi nhận được thông báo lỗi end of file, vì rõ ràng hạt giống ngẫu nhiên cần chứa tất cả các từ mà tệp được sắp xếp chứa. Điều đó có đúng không? Nếu có, làm thế nào tôi nên tạo một hạt giống ngẫu nhiên tốt cho nhu cầu của tôi? Nếu không, bằng cách nào khác tôi có thể ngẫu nhiên các tệp song song? Tôi nghĩ về việc dán chúng lại với nhau, ngẫu nhiên và sau đó tách ra một lần nữa. Tuy nhiên, điều này có vẻ xấu vì trước tiên tôi cần tìm một dấu phân cách không xảy ra trong các tệp.


1
Bạn đã gặp lỗi đó vì Random_file của bạn không chứa đủ byte ... Xem random sources. Đối với paste, bạn có thể sử dụng như dấu phân cách một số char ascii thấp không có khả năng xảy ra trong các tệp của bạn (như \x02, \x03...).
don_crissti

Được rồi, bất cứ điều gì tôi muốn ngẫu nhiên, nếu tôi sử dụng / dev / urandom, tôi sẽ tốt để đi, phải không? Dấu phân cách dán là một mẹo hay, cảm ơn!
conipo

Câu trả lời:


10

Tôi không biết có cách nào thanh lịch hơn không nhưng cách này hiệu quả với tôi:

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

Kết quả:

$ 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

Nhưng các tập tin phải có cùng số dòng chính xác.


Tài liệu GNU Coreutils cũng cung cấp một giải pháp tốt cho tính ngẫu nhiên lặp đi lặp lại bằng cách sử dụng opensslnhư một trình tạo ngẫu nhiên có hạt:

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

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)

Tuy nhiên, hãy cân nhắc sử dụng hạt giống tốt hơn "42", trừ khi bạn muốn bất kỳ ai khác có thể sao chép "kết quả" ngẫu nhiên của bạn.


Công việc này như một cái duyên vậy. Bạn có phiền giải thích các bước mà bạn đã thực hiện? Lệnh tee đảm bảo rằng cùng một số ngẫu nhiên được lưu trữ trong cả ba ống, phải không? Tại sao nó cũng cần xuất ra / dev / null? Và nó có tự động đảm bảo rằng có đủ byte và end of filelỗi không xảy ra không?
conipo

/dev/nullbởi vì teecũng in stdout. Có thể sử dụng > threerandomthay thế nhưng nó khó hơn để kịch bản. Các đường ống được đặt tên sẽ tạo ra càng nhiều dữ liệu ngẫu nhiên cần thiết, vì vậy bạn không cần phải biết trước mình sẽ cần bao nhiêu.
frostschutz

Ok, và tại sao nó không thể là một đường ống mà bạn sử dụng làm nguồn ngẫu nhiên cho cả 3 lần xáo trộn lần lượt?
conipo

2
Bạn không thể đọc cùng một dữ liệu ba lần từ một ống. Bạn phải ghép kênh bằng cách nào đó và đó là những gì tee...
frostschutz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.