Bagaimana cara mengacak baris dalam file menggunakan alat standar di Red Hat Linux?
Saya tidak memiliki shuf
perintah, jadi saya mencari sesuatu seperti perl
atau awk
satu baris yang menyelesaikan tugas yang sama.
Bagaimana cara mengacak baris dalam file menggunakan alat standar di Red Hat Linux?
Saya tidak memiliki shuf
perintah, jadi saya mencari sesuatu seperti perl
atau awk
satu baris yang menyelesaikan tugas yang sama.
Jawaban:
Dan Anda mendapatkan Perl one-liner!
perl -MList::Util -e 'print List::Util::shuffle <>'
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:
#!/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
Belum teruji, tapi semoga berhasil.
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 kecuali Killed
. Adakah ide jika solusi perl memuat semuanya ke dalam memori juga, atau adakah masalah lain yang saya hadapi?
Um, jangan lupa
sort --random-sort
brew install coreutils
Semua utilitas diawali dengan ag jadi: gsort --random-sort
atau gshuf
akan berfungsi seperti yang diharapkan
gsort
dan gshuf
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. Kemudian shuf
diurutkan dalam satu menit.
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 dengan shuf
), tidak peduli berapa banyak memori yang saya alokasikan.
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
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.
$RANDOM
), tetapi -1 untuk memotong data. Mengganti while read f
dengan while IFS= read -r f
akan mencegah read
penghapusan spasi kosong di depan dan di belakang (lihat jawaban ini ) dan mencegah pemrosesan garis miring terbalik. Menggunakan string acak dengan panjang tetap akan mencegah cut
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:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
Dan untuk mencetak hanya satu baris acak:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
Tapi lihat posting ini untuk kekurangan python random.shuffle()
. Ini tidak akan bekerja dengan baik dengan banyak (lebih dari 2080) elemen.
Terkait dengan jawaban Jim:
Saya ~/.bashrc
berisi yang berikut:
unsort ()
{
LC_ALL=C sort -R "$@"
}
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,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 bahwa print
terjadi di loop yang sama file sedang dibaca, dan print shuffle <>
tidak keluar sampai setelah semua file input telah dibaca dan ditutup.
Sebagai solusi yang lebih singkat,
perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'
akan mengacak file di tempat. ( -n
artinya "membungkus kode dalam satu while (<>) {...}
lingkaran; BEGIN{undef$/}
membuat Perl beroperasi pada file-at-a-time alih-alih baris-pada-waktu, dan split/^/m
diperlukan karena $_=<>
telah dilakukan secara implisit dengan seluruh file, bukan baris.)
FreeBSD memiliki utilitas acaknya sendiri:
cat $file | random | ...
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.
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
Atau dapatkan dari MacPorts:
$ sudo port install coreutils
dan / atau
$ /opt/local//libexec/gnubin/sort --random-sort