ฉันจะสุ่มเส้นในไฟล์โดยใช้เครื่องมือมาตรฐานบน Red Hat Linux ได้อย่างไร


102

ฉันจะสุ่มเส้นในไฟล์โดยใช้เครื่องมือมาตรฐานบน Red Hat Linux ได้อย่างไร

ฉันไม่มีshufคำสั่งดังนั้นฉันกำลังมองหาบางอย่างเช่น a perlหรือawk one-liner ที่ทำงานเดียวกันให้สำเร็จ


1
ฉันถามคำถามเกือบเหมือนกัน [ stackoverflow.com/questions/286640/…
Steve Schnepp


ฉันถือว่า gcc เป็นเครื่องมือมาตรฐานใน linux ใด ๆ ; D
msb

คำตอบ:


64

และ Perl หนึ่งซับที่คุณจะได้รับ!

perl -MList::Util -e 'print List::Util::shuffle <>'

ใช้โมดูล แต่โมดูลเป็นส่วนหนึ่งของการแจกแจงรหัส Perl หากยังไม่ดีพอคุณอาจลองหมุนเอง

ฉันลองใช้สิ่งนี้กับ-iแฟล็ก ("แก้ไขในสถานที่") เพื่อให้มันแก้ไขไฟล์ เอกสารแนะนำว่าควรใช้งานได้ แต่ไม่ได้ผล มันยังคงแสดงไฟล์ที่สับเป็น stdout แต่คราวนี้มันจะลบต้นฉบับ ฉันขอแนะนำให้คุณอย่าใช้มัน

พิจารณาเชลล์สคริปต์:

#!/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

ยังไม่ทดสอบ แต่หวังว่าจะได้ผล


ในการสำรองไฟล์ต้นฉบับคุณสามารถต่อท้ายส่วนขยายของแฟล็ก
Steve Schnepp

ฉันมักจะเป็นแฟน Perl ruby -e 'puts STDIN.readlines.shuffle'แต่มาข้ามเช่นทับทิมซึ่งมีประโยชน์ในการเป็นสั้น: จะต้องมีการทดสอบปัจจัยการผลิตขนาดใหญ่เพื่อดูว่าความเร็วเทียบได้หรือไม่ (ใช้งานได้กับ OS X ด้วย)
mivk

ตามความคิดเห็นด้านล่างshufโหลดทุกอย่างลงในหน่วยความจำดังนั้นจึงใช้ไม่ได้กับไฟล์ขนาดใหญ่อย่างแท้จริง (ของฉันคือ ~ 300GB tsv) Perl สคริปต์นี้ล้มเหลวในเหมืองเกินไป Killedแต่มีข้อผิดพลาดไม่มียกเว้น มีความคิดอย่างไรหากโซลูชัน perl กำลังโหลดทุกอย่างลงในหน่วยความจำด้วยหรือมีปัญหาอื่น ๆ ที่ฉันพบอยู่
seth127

211

อืมอย่าลืม

sort --random-sort

1
ฉันใช้ gnu-coreutils 7.1 (การติดตั้ง gentoo มาตรฐาน) ซึ่งเรียงลำดับด้วยตัวเลือกนี้ไม่แน่ใจว่ามันปรากฏขึ้นเมื่อใดหรือในการใช้งานอื่น ๆ
Jim T

1
ฟีเจอร์นี้ได้รับการยอมรับในวันที่ 10 ธันวาคม พ.ศ. 2548 ซึ่งเป็นรุ่นต่อจากนั้นคือ 5.94 ดังนั้นฉันเดาว่าจะมีให้ใช้งานตั้งแต่เวอร์ชันนั้น
Jim T

41
บน OS X คุณสามารถติดตั้ง gnu coreutils ด้วย homebrew: brew install coreutilsutils ทั้งหมดขึ้นต้นด้วย ag ดังนั้น: gsort --random-sortหรือgshufจะทำงานตามที่คาดไว้
mike

3
+1 @mike. ฉันใช้ Macports และฉันก็มีgsortและgshufติดตั้งเมื่อฉันทำport install coreutils
Noah Sussman

10
วิธีนี้จะดีก็ต่อเมื่อเส้นของคุณไม่มีการซ้ำ หากเป็นเช่นนั้นอินสแตนซ์ทั้งหมดของบรรทัดนั้นจะปรากฏติดกัน ลองใช้shufแทน (บน linux)
Ali J

118

shuf เป็นวิธีที่ดีที่สุด

sort -Rช้าอย่างเจ็บปวด ฉันเพิ่งพยายามจัดเรียงไฟล์ 5GB ฉันยอมแพ้หลังจาก 2.5 ชั่วโมง จากนั้นshufจัดเรียงในหนึ่งนาที


นี่มันเยี่ยมมาก ดูเหมือนว่าจะอยู่ใน GNU coreutils
ariddell

4
ฉันสงสัยว่าสาเหตุที่sort -Rช้าคือการคำนวณแฮชสำหรับแต่ละบรรทัด จากเอกสาร: " เรียงลำดับโดยการแฮชคีย์อินพุตจากนั้นเรียงลำดับค่าแฮช "
Joe Flynn

13
ระวังshufโหลดทุกอย่างในหน่วยความจำ
jfs

1
@benroth: จากสิ่งที่ฉันสามารถบอกได้ด้วยจำนวนอินพุตที่มากขึ้นจริง ๆ การเพิ่มหน่วยความจำสามารถช่วยได้บ้างแต่ก็ยังช้าโดยรวม ในการทดสอบของฉันเรียงลำดับแฟ้มใส่ 1 ล้านเส้นที่สร้างขึ้นด้วยseq -f 'line %.0f' 1000000เอาเดียวกันยาวเวลาในการประมวลผล (มากนานกว่าด้วยshuf) ไม่ว่าหน่วยความจำมากฉันจัดสรร
ข้อเท้า 0

1
@ mklement0 คุณพูดถูก! ฉันเพิ่งลองใช้ไฟล์ที่ใหญ่กว่าที่เคยมีมาและการแฮชดูเหมือนจะเป็นปัญหาคอขวดอย่างแน่นอน
benroth

23
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-

อ่านไฟล์นำหน้าทุกบรรทัดด้วยตัวเลขสุ่มเรียงไฟล์บนคำนำหน้าแบบสุ่มเหล่านั้นตัดคำนำหน้าหลังจากนั้น ซับเดียวซึ่งควรใช้กับเปลือกกึ่งโมเดิร์นใดก็ได้

แก้ไข: รวมคำพูดของ Richard Hansen


1
วิธีนี้ใช้ได้ผลและเป็นโซลูชันที่สร้างสรรค์ แต่จะลบช่องว่างชั้นนำบนเส้น
Chris Lutz

@Chris เปลี่ยนการตัดครั้งสุดท้ายเป็น | sed 's / ^ [^ \ t] * \ t //' ควรแก้ไข
bdonlan

ขอชื่นชมความเรียบง่ายของแนวทาง!
Shashikant Kore

3
+1 สำหรับความสอดคล้องของ POSIX (ยกเว้น$RANDOM) แต่ -1 สำหรับการฆ่าข้อมูล การแทนที่while read fด้วยwhile IFS= read -r fจะป้องกันไม่ให้readลบช่องว่างนำหน้าและต่อท้าย (ดูคำตอบนี้ ) และป้องกันการประมวลผลแบ็กสแลช การใช้สตริงสุ่มที่มีความยาวคงที่จะป้องกันไม่ให้cutลบช่องว่างนำหน้า ผลลัพธ์: 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: ขอบคุณการเปลี่ยนแปลงที่แนะนำเหล่านี้เหมาะสมอย่างเห็นได้ชัดฉันแก้ไขโพสต์ของฉันแล้ว
ChristopheD

9

หนึ่งซับสำหรับ python:

python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile

และสำหรับการพิมพ์เพียงบรรทัดเดียวแบบสุ่ม:

python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile

แต่เห็นโพสต์นี้random.shuffle()สำหรับข้อเสียของงูหลามของ มันใช้ไม่ได้กับหลาย ๆ องค์ประกอบ (มากกว่า 2080)


5

เกี่ยวข้องกับคำตอบของ Jim:

ของฉัน~/.bashrcประกอบด้วยสิ่งต่อไปนี้:

unsort ()
{
    LC_ALL=C sort -R "$@"
}

ด้วยการเรียงลำดับของ GNU coreutils -R= --random-sortซึ่งสร้างแฮชแบบสุ่มของแต่ละบรรทัดและจัดเรียงตามมัน กัญชาแบบสุ่มจะไม่นำมาใช้จริงในสถานที่บางอย่างในบางรุ่นเก่า (รถ) LC_ALL=Cทำให้มันกลับมาส่งออกเรียงตามปกติซึ่งเป็นเหตุผลที่ผมตั้ง


เกี่ยวข้องกับคำตอบของ Chris:

perl -MList::Util=shuffle -e'print shuffle<>'

เป็นซับเดียวที่สั้นกว่าเล็กน้อย ( -Mmodule=a,b,cเป็นชวเลขสำหรับ-e 'use module qw(a b c);' .)

เหตุผลที่ทำให้มันง่าย-iไม่ได้ผลสำหรับการสับในสถานที่เพราะ Perl คาดว่าสิ่งที่printเกิดขึ้นในลูปเดียวกันกับไฟล์ที่กำลังอ่านอยู่และprint shuffle <>จะไม่ส่งออกจนกว่าจะมีการอ่านและปิดไฟล์อินพุตทั้งหมด

วิธีแก้ปัญหาสั้น ๆ

perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'

จะสลับไฟล์ในสถานที่ ( -nหมายถึง "ห่อรหัสในการwhile (<>) {...}วนซ้ำBEGIN{undef$/}ทำให้ Perl ดำเนินการกับไฟล์ทีละไฟล์แทนทีละบรรทัดและsplit/^/mเป็นสิ่งที่จำเป็นเนื่องจาก$_=<>ได้ทำโดยปริยายกับไฟล์ทั้งหมดแทนที่จะเป็นบรรทัด)


ย้ำว่า sort -R ไม่มีอยู่ใน OS X แต่ +1 สำหรับคำตอบที่ยอดเยี่ยมของ Perl และคำตอบที่ดีโดยทั่วไป
Chris Lutz

คุณสามารถติดตั้ง GNU coreutils บน OS X ได้ แต่ (อย่างที่ฉันเคยทำในอดีต) คุณต้องระวังไม่ให้เครื่องมือในตัวพัง ... ที่กล่าวกันว่า OP อยู่บน Redhat Linux ซึ่งมี GNU แน่นอน มาตรฐาน coreutils
ephemient

3

เมื่อฉันติดตั้ง coreutils ด้วย homebrew

brew install coreutils

shufnจะสามารถใช้เป็น


ชงนำหน้าคำสั่งทั้งหมดที่มีgเพื่อให้shufกลายเป็นgshufสำหรับฉัน
Jörn

^ นั่นเป็นเพราะพวกเขาไม่ใช่ POSIX หรือฉันเฉยๆ?
Dave Liu


1

FreeBSD มียูทิลิตี้แบบสุ่มของตัวเอง:

cat $file | random | ...

มันอยู่ใน / usr / games / random ดังนั้นหากคุณยังไม่ได้ติดตั้งเกมคุณจะโชคไม่ดี

คุณสามารถพิจารณาติดตั้งพอร์ตเช่น textproc / rand หรือ textproc / msort สิ่งเหล่านี้อาจพร้อมใช้งานบน Linux และ / หรือ Mac OS X หากเป็นปัญหาในการพกพา


-1

บน OSX รับข้อมูลล่าสุดจากhttp://ftp.gnu.org/gnu/coreutils/และสิ่งที่ชอบ

./configure ทำให้ sudo ทำการติดตั้ง

... ควรให้คุณ / usr / local / bin / sort --random-sort

โดยไม่ทำให้สับสน / usr / bin / sort


สิ่งนี้ใช้ไม่ได้สำหรับฉันบน OSX (10.7) ฉันได้รับ "การกำหนดค่า: ข้อผิดพลาด: คอมไพเลอร์ C ไม่สามารถสร้างไฟล์ปฏิบัติการได้"
Dolan Antenucci

@dolan ตรวจสอบสิทธิ์ของคุณ?
Benubird

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.