Làm cách nào tôi có thể sắp xếp ngẫu nhiên các dòng trong tệp bằng các công cụ tiêu chuẩn trên Red Hat Linux?
Tôi không có shuf
lệnh, vì vậy tôi đang tìm kiếm thứ gì đó giống như một perl
hoặc awk
một lớp lót hoàn thành cùng một nhiệm vụ.
Làm cách nào tôi có thể sắp xếp ngẫu nhiên các dòng trong tệp bằng các công cụ tiêu chuẩn trên Red Hat Linux?
Tôi không có shuf
lệnh, vì vậy tôi đang tìm kiếm thứ gì đó giống như một perl
hoặc awk
một lớp lót hoàn thành cùng một nhiệm vụ.
Câu trả lời:
Và một lớp lót Perl bạn nhận được!
perl -MList::Util -e 'print List::Util::shuffle <>'
Nó sử dụng một mô-đun, nhưng mô-đun là một phần của phân phối mã Perl. Nếu điều đó chưa đủ tốt, bạn có thể cân nhắc việc lăn bánh của riêng mình.
Tôi đã thử sử dụng điều này với -i
cờ ("chỉnh sửa tại chỗ") để nó chỉnh sửa tệp. Tài liệu cho thấy nó sẽ hoạt động, nhưng nó không. Nó vẫn hiển thị tệp xáo trộn thành stdout, nhưng lần này nó sẽ xóa tệp gốc. Tôi đề nghị bạn không sử dụng nó.
Hãy xem xét một kịch bản 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
Chưa được kiểm tra, nhưng hy vọng sẽ hoạt động.
ruby -e 'puts STDIN.readlines.shuffle'
. Nó sẽ cần thử nghiệm trên các đầu vào lớn để xem tốc độ có thể so sánh được hay không. (cũng hoạt động trên OS X)
shuf
tải mọi thứ vào bộ nhớ, vì vậy nó không hoạt động với một tệp thực sự lớn (của tôi là ~ 300GB tsv). Tập lệnh perl này của tôi cũng không thành công, nhưng không có lỗi ngoại trừ Killed
. Bất kỳ ý tưởng nào nếu giải pháp perl cũng đang tải mọi thứ vào bộ nhớ hoặc có một số vấn đề khác mà tôi đang gặp phải?
Ừm, đừng quên
sort --random-sort
brew install coreutils
Tất cả các utils được bắt đầu với ag vậy: gsort --random-sort
hoặc gshuf
sẽ làm việc như mong đợi
gsort
và gshuf
cài đặt khi tôi đã làmport install coreutils
shuf
thay thế (trên linux).
shuf
là cách tốt nhất.
sort -R
chậm một cách đau đớn. Tôi vừa cố gắng sắp xếp tệp 5GB. Tôi đã bỏ cuộc sau 2,5 giờ. Sau đó, shuf
sắp xếp nó trong một phút.
sort -R
chậm là tính toán một hàm băm cho mỗi dòng. Từ các tài liệu: " Sắp xếp theo băm các phím đầu vào và sau đó sắp xếp các giá trị băm. "
shuf
tải mọi thứ vào bộ nhớ.
seq -f 'line %.0f' 1000000
mất cùng một thời gian dài để xử lý (nhiều, lâu hơn với shuf
), bất kể tôi đã cấp bao nhiêu bộ nhớ.
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Đọc tệp, thêm vào trước mỗi dòng một số ngẫu nhiên, sắp xếp tệp trên các tiền tố ngẫu nhiên đó, cắt các tiền tố sau đó. Một lớp lót sẽ hoạt động trong bất kỳ lớp vỏ bán hiện đại nào.
CHỈNH SỬA: kết hợp nhận xét của Richard Hansen.
$RANDOM
), nhưng -1 cho việc xử lý dữ liệu. Thay thế while read f
bằng while IFS= read -r f
sẽ ngăn chặn read
việc xóa khoảng trắng ở đầu và cuối (xem câu trả lời này ) và ngăn việc xử lý dấu gạch chéo ngược. Việc sử dụng một chuỗi ngẫu nhiên có độ dài cố định sẽ ngăn việc cut
xóa khoảng trắng ở đầu. Kết quả: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Một lớp lót cho python:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
Và để in chỉ một dòng ngẫu nhiên:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
Nhưng hãy xem bài đăng này để biết những hạn chế của python random.shuffle()
. Nó sẽ không hoạt động tốt với nhiều (hơn 2080) phần tử.
Liên quan đến câu trả lời của Jim:
Của tôi ~/.bashrc
chứa những thứ sau:
unsort ()
{
LC_ALL=C sort -R "$@"
}
Với cách sắp xếp của GNU coreutils, -R
= --random-sort
, tạo ra một hàm băm ngẫu nhiên của mỗi dòng và sắp xếp theo nó. Hàm băm ngẫu nhiên sẽ không thực sự được sử dụng trong một số ngôn ngữ trong một số phiên bản cũ hơn (lỗi), khiến nó trả về đầu ra được sắp xếp bình thường, đó là lý do tại sao tôi đặt LC_ALL=C
.
Liên quan đến câu trả lời của Chris:
perl -MList::Util=shuffle -e'print shuffle<>'
là một lớp lót ngắn hơn một chút. ( -Mmodule=a,b,c
là viết tắt của -e 'use module qw(a b c);'
.)
Lý do đơn giản -i
không hoạt động cho việc xáo trộn tại chỗ là bởi vì Perl hy vọng rằng điều đó print
xảy ra trong cùng một vòng lặp mà tệp đang được đọc và print shuffle <>
không xuất ra cho đến khi tất cả các tệp đầu vào đã được đọc và đóng.
Như một giải pháp ngắn hơn,
perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'
sẽ xáo trộn các tệp tại chỗ. ( -n
có nghĩa là "quấn mã trong một while (<>) {...}
vòng lặp; BEGIN{undef$/}
làm cho Perl hoạt động trên các tệp tại một thời điểm thay vì các dòng tại một thời điểm và split/^/m
cần thiết vì $_=<>
đã được thực hiện ngầm với toàn bộ tệp thay vì các dòng.)
FreeBSD có tiện ích ngẫu nhiên của riêng nó:
cat $file | random | ...
Nó nằm trong / usr / games / random, vì vậy nếu bạn chưa cài đặt trò chơi, bạn sẽ không gặp may.
Bạn có thể cân nhắc cài đặt các cổng như textproc / rand hoặc textproc / msort. Những thứ này cũng có thể có sẵn trên Linux và / hoặc Mac OS X, nếu mối quan tâm về tính di động.
Trên OSX, tải trang mới nhất từ http://ftp.gnu.org/gnu/coreutils/ và những thứ như
./configure make sudo make install
... nên cung cấp cho bạn / usr / local / bin / sort --random-sort
mà không làm rối tung / usr / bin / sort
Hoặc tải nó từ MacPorts:
$ sudo port install coreutils
và / hoặc
$ /opt/local//libexec/gnubin/sort --random-sort