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?


102

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ó shuflệnh, vì vậy tôi đang tìm kiếm thứ gì đó giống như một perlhoặc awkmột lớp lót hoàn thành cùng một nhiệm vụ.


1
Tôi đã hỏi gần như cùng một câu hỏi [ stackoverflow.com/questions/286640/…
Steve Schnepp


Tôi coi gcc là một công cụ tiêu chuẩn trong bất kỳ linux nào. ; D
msb

Câu trả lời:


64

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 -icờ ("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.


Để sao lưu tệp gốc, bạn có thể thêm phần mở rộng vào cờ -i [ perldoc.perl.org/perlrun.html]
Steve Schnepp

Tôi thường là một fan hâm mộ Perl, nhưng đi qua ví dụ ruby này trong đó có lợi ích của việc ngắn hơn: 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)
mivk

mỗi nhận xét bên dưới, shuftả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?
seth127,

211

Ừm, đừng quên

sort --random-sort

1
Chà, tôi đang sử dụng gnu-coreutils 7.1 (cài đặt gentoo tiêu chuẩn), có sắp xếp với tùy chọn này, không chắc khi nào nó xuất hiện hoặc nếu nó ở trong các triển khai khác.
Jim T

1
Tính năng này được cam kết vào ngày 10 tháng 12 năm 2005, bản phát hành sau đó là 5.94, vì vậy tôi đoán nó đã có sẵn kể từ phiên bản đó.
Jim T

41
Trên OS X bạn có thể cài đặt gnu coreutils với homebrew: brew install coreutilsTất cả các utils được bắt đầu với ag vậy: gsort --random-sorthoặc gshufsẽ làm việc như mong đợi
mike

3
+1 @mike. Tôi sử dụng Macports và tôi cũng đã có gsortgshufcài đặt khi tôi đã làmport install coreutils
Noah Sussman

10
Giải pháp này chỉ tốt nếu dòng của bạn không có sự lặp lại. Nếu có, tất cả các trường hợp của dòng đó sẽ xuất hiện bên cạnh nhau. Cân nhắc sử dụng shufthay thế (trên linux).
Ali J

118

shuf là cách tốt nhất.

sort -Rchậ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 đó, shufsắp xếp nó trong một phút.


Điều đó thật tuyệt. Nó dường như nằm trong lõi GNU.
ariddell

4
Tôi nghi ngờ lý do sort -Rchậ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. "
Joe Flynn

13
hãy cẩn thận, shuftải mọi thứ vào bộ nhớ.
jfs

1
@benroth: Theo những gì tôi có thể nói, với số lượng đầu vào thực sự lớn, việc tăng bộ nhớ có thể giúp ích phần nào , nhưng nhìn chung thì nó vẫn chậm. Trong các thử nghiệm của tôi, việc sắp xếp một tệp đầu vào 1 triệu dòng được tạo bằng seq -f 'line %.0f' 1000000mấ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ớ.
mklement0

1
@ mklement0, bạn nói đúng! Tôi vừa thử nó với một tệp lớn hơn nhiều so với những gì tôi đã có trước đây và việc băm dường như thực sự là nút thắt cổ chai.
benroth

23
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.


1
Điều này hoạt động và là một giải pháp sáng tạo, nhưng sẽ xóa khoảng trắng hàng đầu trên các dòng.
Chris Lutz

@Chris thay đổi đoạn cắt cuối cùng thành | sed 's / ^ [^ \ t] * \ t //' nên sửa lỗi đó
bdonlan

Kudo cho sự đơn giản của cách tiếp cận!
Shashikant Kore

3
+1 cho sự tuân thủ POSIX (ngoại trừ $RANDOM), nhưng -1 cho việc xử lý dữ liệu. Thay thế while read fbằng while IFS= read -r fsẽ ngăn chặn readviệ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 cutxó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-
Richard Hansen

3
@Richard Hansen: Cảm ơn, những thay đổi được đề xuất này rõ ràng là phù hợp, tôi đã chỉnh sửa bài đăng của mình.
ChristopheD

9

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ử.


5

Liên quan đến câu trả lời của Jim:

Của tôi ~/.bashrcchứ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,clà viết tắt của -e 'use module qw(a b c);'.)

Lý do đơn giản -ikhô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 đó printxả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ỗ. ( -ncó 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/^/mcần thiết vì $_=<>đã được thực hiện ngầm với toàn bộ tệp thay vì các dòng.)


Nhắc lại rằng sắp xếp -R không tồn tại trên OS X, nhưng +1 cho một số câu trả lời Perl tuyệt vời và một câu trả lời tuyệt vời nói chung.
Chris Lutz

Bạn có thể cài đặt coreutils GNU trên OS X, nhưng (như tôi đã làm trước đây) bạn phải cẩn thận để không làm hỏng các công cụ tích hợp sẵn ... Điều đó đang nói, OP trên Redhat Linux, chắc chắn có GNU tiêu chuẩn coreutils.
ephemient

3

Khi tôi cài đặt coreutils với homebrew

brew install coreutils

shuftrở nên có sẵn dưới dạng n.


brew tiền tố tất cả các lệnh với gquá shufđã trở thành gshufđối với tôi.
Jörn

^ Đó là bởi vì chúng không phải là POSIX, hay tôi chỉ hoàn toàn tắt?
Dave Liu,

1

Mac OS X với DarwinPorts:

sudo port install unsort
cat $file | unsort | ...

1

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.


-1

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


điều này không hoạt động với tôi trên OSX (10.7). Tôi nhận được "config: error: Trình biên dịch C không thể tạo tệp thi hành".
Dolan Antenucci,

@dolan Kiểm tra quyền của bạn?
Benubird

-1

Hoặc tải nó từ MacPorts:

$ sudo port install coreutils

và / hoặc

$ /opt/local//libexec/gnubin/sort --random-sort
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.