Ini menggunakan modul, tetapi modul tersebut adalah bagian dari distribusi kode Perl. Jika itu tidak cukup baik, Anda dapat mempertimbangkan untuk menggulungnya sendiri.
Saya mencoba menggunakan ini dengan -ibendera ("edit-in-place") untuk mengedit file. Dokumentasi menyarankan itu harus berfungsi, tetapi tidak. Ini masih menampilkan file yang diacak ke stdout, tapi kali ini menghapus aslinya. Saya sarankan Anda tidak menggunakannya.
Pertimbangkan skrip shell:
#!/bin/sh
if [[ $# -eq 0 ]]
then
echo "Usage: $0 [file ...]"
exit 1
fi
for i in "$@"
do
perl -MList::Util -e 'print List::Util::shuffle <>' $i > $i.new
if [[ `wc -c $i` -eq `wc -c $i.new` ]]
then
mv $i.new $i
else
echo "Error for file $i!"
fi
done
Saya biasanya penggemar Perl, tapi datang di contoh ruby ini yang memiliki manfaat yang lebih pendek: ruby -e 'puts STDIN.readlines.shuffle'. Diperlukan pengujian pada input besar untuk melihat apakah kecepatannya sebanding. (juga bekerja pada OS X)
mivk
per komentar di bawah, shufmemuat semuanya ke dalam memori, sehingga tidak berfungsi dengan file yang benar-benar besar (milik saya ~ 300GB tsv). Skrip perl ini juga gagal pada saya, tetapi tanpa kesalahan kecuali Killed. Adakah ide jika solusi perl memuat semuanya ke dalam memori juga, atau adakah masalah lain yang saya hadapi?
Saya menggunakan gnu-coreutils 7.1 (instalasi gentoo standar), yang memiliki sort dengan opsi ini, tidak yakin kapan muncul, atau apakah itu dalam implementasi lain.
Jim T
1
Fitur ini dibuat pada tanggal 10 Desember 2005, rilis berikutnya adalah 5.94, jadi saya rasa itu sudah tersedia sejak versi itu.
Jim T
41
Di OS X Anda dapat menginstal gnu coreutils dengan homebrew: brew install coreutilsSemua utilitas diawali dengan ag jadi: gsort --random-sortatau gshufakan berfungsi seperti yang diharapkan
mike
3
+1 @ mike. Saya menggunakan Macports dan saya juga memiliki gsortdan gshufmenginstal ketika saya melakukannyaport install coreutils
Noah Sussman
10
Solusi ini hanya bagus jika baris Anda tidak memiliki pengulangan. Jika ya, semua contoh dari baris itu akan muncul bersebelahan. Pertimbangkan untuk menggunakan shufsebagai gantinya (di linux).
Ali J
118
shuf adalah cara terbaik.
sort -Rsangat lambat. Saya hanya mencoba mengurutkan file 5GB. Saya menyerah setelah 2,5 jam. Kemudian shufdiurutkan dalam satu menit.
@benroth: Dari apa yang saya tahu, dengan jumlah masukan benar-benar besar meningkatkan memori dapat membantu agak , tapi masih lambat secara keseluruhan. Dalam pengujian saya, menyortir file input 1 juta baris yang dibuat dengan seq -f 'line %.0f' 1000000memakan waktu yang sama dan lama untuk diproses (jauh, lebih lama daripada dengan shuf), tidak peduli berapa banyak memori yang saya alokasikan.
mklement0
1
@ mklement0, Anda benar! Saya baru saja mencobanya dengan file yang jauh lebih besar dari yang saya miliki sebelumnya, dan hashing tampaknya memang menjadi penghambat.
Baca file, tambahkan setiap baris dengan nomor acak, urutkan file pada awalan acak tersebut, potong awalan setelahnya. Satu baris yang seharusnya berfungsi di shell semi-modern.
Ini berfungsi, dan merupakan solusi kreatif, tetapi akan menghapus spasi kosong di baris.
Chris Lutz
@Chris mengubah potongan terakhir menjadi | sed 's / ^ [^ \ t] * \ t //' harus memperbaikinya
bdonlan
Kudos untuk kesederhanaan pendekatannya!
Shashikant Kore
3
+1 untuk kesesuaian POSIX (kecuali untuk $RANDOM), tetapi -1 untuk memotong data. Mengganti while read fdengan while IFS= read -r fakan mencegah readpenghapusan spasi kosong di depan dan di belakang (lihat jawaban ini ) dan mencegah pemrosesan garis miring terbalik. Menggunakan string acak dengan panjang tetap akan mencegah cutpenghapusan spasi kosong di depan. Hasil: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Richard Hansen
3
@ Richard Hansen: Terima kasih, perubahan yang disarankan ini jelas sesuai, saya telah mengedit posting saya.
Dengan GNU coreutils's sort, -R= --random-sort, yang menghasilkan hash acak dari setiap baris dan mengurutkannya. Hash acak tidak akan benar-benar digunakan di beberapa lokal di beberapa versi yang lebih lama (buggy), menyebabkannya mengembalikan output yang diurutkan normal, itulah sebabnya saya menetapkan LC_ALL=C.
Terkait dengan jawaban Chris:
perl -MList::Util=shuffle -e'print shuffle<>'
adalah satu baris yang sedikit lebih pendek. ( -Mmodule=a,b,cadalah singkatan dari -e 'use module qw(a b c);'.)
Alasan memberikannya sederhana -itidak berfungsi untuk pengacakan di tempat adalah karena Perl mengharapkan bahwa printterjadi di loop yang sama file sedang dibaca, dan print shuffle <>tidak keluar sampai setelah semua file input telah dibaca dan ditutup.
akan mengacak file di tempat. ( -nartinya "membungkus kode dalam satu while (<>) {...}lingkaran; BEGIN{undef$/}membuat Perl beroperasi pada file-at-a-time alih-alih baris-pada-waktu, dan split/^/mdiperlukan karena $_=<>telah dilakukan secara implisit dengan seluruh file, bukan baris.)
Mengulangi semacam itu -R tidak ada di OS X, tetapi +1 untuk beberapa jawaban Perl yang bagus, dan jawaban yang bagus secara umum.
Chris Lutz
Anda dapat menginstal GNU coreutils di OS X, tetapi (seperti yang telah saya lakukan di masa lalu) Anda harus berhati-hati untuk tidak merusak alat bawaan ... Meskipun demikian, OP ada di Redhat Linux, yang pasti memiliki GNU standar coreutils.
Ada di / usr / games / random, jadi jika Anda belum menginstal game, Anda kurang beruntung.
Anda dapat mempertimbangkan untuk menginstal port seperti textproc / rand atau textproc / msort. Ini mungkin tersedia di Linux dan / atau Mac OS X, jika portabilitas menjadi perhatian.
Jawaban:
Dan Anda mendapatkan Perl one-liner!
Ini menggunakan modul, tetapi modul tersebut adalah bagian dari distribusi kode Perl. Jika itu tidak cukup baik, Anda dapat mempertimbangkan untuk menggulungnya sendiri.
Saya mencoba menggunakan ini dengan
-i
bendera ("edit-in-place") untuk mengedit file. Dokumentasi menyarankan itu harus berfungsi, tetapi tidak. Ini masih menampilkan file yang diacak ke stdout, tapi kali ini menghapus aslinya. Saya sarankan Anda tidak menggunakannya.Pertimbangkan skrip shell:
Belum teruji, tapi semoga berhasil.
sumber
ruby -e 'puts STDIN.readlines.shuffle'
. Diperlukan pengujian pada input besar untuk melihat apakah kecepatannya sebanding. (juga bekerja pada OS X)shuf
memuat semuanya ke dalam memori, sehingga tidak berfungsi dengan file yang benar-benar besar (milik saya ~ 300GB tsv). Skrip perl ini juga gagal pada saya, tetapi tanpa kesalahan kecualiKilled
. Adakah ide jika solusi perl memuat semuanya ke dalam memori juga, atau adakah masalah lain yang saya hadapi?Um, jangan lupa
sumber
brew install coreutils
Semua utilitas diawali dengan ag jadi:gsort --random-sort
ataugshuf
akan berfungsi seperti yang diharapkangsort
dangshuf
menginstal ketika saya melakukannyaport install coreutils
shuf
sebagai gantinya (di linux).shuf
adalah cara terbaik.sort -R
sangat lambat. Saya hanya mencoba mengurutkan file 5GB. Saya menyerah setelah 2,5 jam. Kemudianshuf
diurutkan dalam satu menit.sumber
sort -R
lambat adalah karena menghitung hash untuk setiap baris. Dari dokumen: " Urutkan menurut hashing kunci input dan kemudian urutkan nilai hash. "shuf
muat semuanya di memori.seq -f 'line %.0f' 1000000
memakan waktu yang sama dan lama untuk diproses (jauh, lebih lama daripada denganshuf
), tidak peduli berapa banyak memori yang saya alokasikan.Baca file, tambahkan setiap baris dengan nomor acak, urutkan file pada awalan acak tersebut, potong awalan setelahnya. Satu baris yang seharusnya berfungsi di shell semi-modern.
EDIT: memasukkan pernyataan Richard Hansen.
sumber
$RANDOM
), tetapi -1 untuk memotong data. Menggantiwhile read f
denganwhile IFS= read -r f
akan mencegahread
penghapusan spasi kosong di depan dan di belakang (lihat jawaban ini ) dan mencegah pemrosesan garis miring terbalik. Menggunakan string acak dengan panjang tetap akan mencegahcut
penghapusan spasi kosong di depan. Hasil:cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Satu baris untuk python:
Dan untuk mencetak hanya satu baris acak:
Tapi lihat posting ini untuk kekurangan python
random.shuffle()
. Ini tidak akan bekerja dengan baik dengan banyak (lebih dari 2080) elemen.sumber
Terkait dengan jawaban Jim:
Saya
~/.bashrc
berisi yang berikut:Dengan GNU coreutils's sort,
-R
=--random-sort
, yang menghasilkan hash acak dari setiap baris dan mengurutkannya. Hash acak tidak akan benar-benar digunakan di beberapa lokal di beberapa versi yang lebih lama (buggy), menyebabkannya mengembalikan output yang diurutkan normal, itulah sebabnya saya menetapkanLC_ALL=C
.Terkait dengan jawaban Chris:
adalah satu baris yang sedikit lebih pendek. (
-Mmodule=a,b,c
adalah singkatan dari-e 'use module qw(a b c);'
.)Alasan memberikannya sederhana
-i
tidak berfungsi untuk pengacakan di tempat adalah karena Perl mengharapkan bahwaprint
terjadi di loop yang sama file sedang dibaca, danprint shuffle <>
tidak keluar sampai setelah semua file input telah dibaca dan ditutup.Sebagai solusi yang lebih singkat,
akan mengacak file di tempat. (
-n
artinya "membungkus kode dalam satuwhile (<>) {...}
lingkaran;BEGIN{undef$/}
membuat Perl beroperasi pada file-at-a-time alih-alih baris-pada-waktu, dansplit/^/m
diperlukan karena$_=<>
telah dilakukan secara implisit dengan seluruh file, bukan baris.)sumber
Ketika saya menginstal coreutils dengan homebrew
shuf
menjadi tersedia sebagain
.sumber
g
begitushuf
menjadigshuf
bagi saya.Mac OS X dengan DarwinPorts:
sumber
FreeBSD memiliki utilitas acaknya sendiri:
Ada di / usr / games / random, jadi jika Anda belum menginstal game, Anda kurang beruntung.
Anda dapat mempertimbangkan untuk menginstal port seperti textproc / rand atau textproc / msort. Ini mungkin tersedia di Linux dan / atau Mac OS X, jika portabilitas menjadi perhatian.
sumber
Di OSX, ambil yang terbaru dari http://ftp.gnu.org/gnu/coreutils/ dan semacamnya
./configure make sudo make install
... harus memberi Anda / usr / local / bin / sort --random-sort
tanpa mengacaukan / usr / bin / sort
sumber
Atau dapatkan dari MacPorts:
dan / atau
sumber