วิธีการสุ่มเอาท์พุทจาก seq?


11

ฉันรู้ว่าฉันสามารถใช้seqเพื่อสร้างรายการตัวเลขแบบสุ่ม: 1, 2, 3, 4 ...

ฉันต้องการให้ตัวเลขเหล่านั้นเรียงลำดับแบบสุ่มเช่น 3, 1, 4, 2 ...

ฉันรู้ว่าฉันสามารถใช้shufเพื่อสลับบรรทัดไฟล์ ดังนั้นฉันสามารถใช้seqเพื่อเขียนตัวเลขสุ่มไปยังไฟล์แล้วใช้shufเพื่อสับเปลี่ยนพวกเขา - หรือเขียนฟังก์ชันสับเปลี่ยนบางประเภท แต่ดูเหมือนว่าจะซับซ้อนโดยไม่จำเป็น มีวิธีที่ง่ายกว่าในการสุ่มรายการในอาเรย์ด้วยคำสั่งเดียว?

คำตอบ:


16

shufคุณก็สามารถท่อออกไป

$ seq 100 | shuf

ตัวอย่าง

$ seq 10 | shuf
2
6
4
8
1
3
10
7
9
5

pasteหากคุณต้องการที่จะออกในแนวนอนแล้วท่อมัน

$ seq 10 | shuf | paste - -s -d ' '
1 6 9 3 8 4 10 7 2 5 

$ seq 10 | shuf | paste - -s -d ' '
7 4 6 1 8 3 10 5 9 2 

$ seq 10 | shuf | paste - -s -d ' '
9 8 3 6 1 2 10 4 7 5 

ต้องการใช้เครื่องหมายจุลภาคในระหว่างหรือไม่ เปลี่ยนตัวคั่นเป็นpaste:

$ seq 10 | shuf | paste - -s -d ','
2,4,9,1,8,7,3,5,10,6

แต่คุณต้องฟอร์แมตด้วยการใช้เครื่องหมายคอมม่า echo $(seq 10 | shuf)เข้ามาใกล้ แต่ไม่ทำเครื่องหมายจุลภาค
mikeserv

มันเป็นแนวนอนก่อนpaste...
mikeserv

@mikeserv - เปลี่ยนไปรอบ ๆ
slm

ใช่. ไปแล้ว ฉันไม่รู้ว่าpasteทำอย่างนั้น ขอบคุณที่สอนฉัน มี upvote
mikeserv

@mikeserv - ใช่อ่านผ่านทางเว็บไซต์ที่กำลังมองหาที่เหมืองทั้งสเตฟานหรือกิลส์ของ A ใช้และjoin pasteเครื่องมือทั้งสองนั้นมีประสิทธิภาพมาก
slm

3

มีวิธีที่ง่ายกว่าในการสุ่มรายการในอาเรย์ด้วยคำสั่งเดียว?

สมมติว่าคุณมีจำนวนเต็มทศนิยม:

arr=(4 8 14 18 24 29 32 37 42)

คุณสามารถใช้printfและshufเพื่อสุ่มองค์ประกอบของอาร์เรย์:

$ arr=($(printf "%d\n" "${arr[@]}" | shuf))
$ echo "${arr[@]}"
4 37 32 14 24 8 29 42 18

(ข้างต้นถือว่าคุณไม่ได้แก้ไข$IFS)


หากสิ่งที่คุณต้องการคือตัวเลขสุ่มระหว่างจำนวนเต็มสองจำนวนพูด10และ20คุณไม่จำเป็นต้องมีกระบวนการพิเศษอื่นใดนอกจากshufโดยใช้-iตัวเลือก:

$ shuf -i 10-20
12
10
20
14
16
19
13
11
18
17
15

ข้อความจากman shuf:

   -i, --input-range=LO-HI
          treat each number LO through HI as an input line

แย่จัง ฉันเห็นด้วยเช่นกันshuf --helpแต่ฉันพยายามใช้shuf -i 1 10โดยไม่มีการแทรกแซง-dash.โอ้ดีการทำงานดี - มี upvote ของฉัน
mikeserv

2
printf '%s, ' `seq 1 10 | shuf`

คุณไม่ต้องการแม้แต่การforวนซ้ำ

เอาท์พุท

7, 3, 4, 10, 2, 9, 1, 8, 5, 6,

ในการรับมันมาในเชลล์อาเรย์คุณต้องทำ:

( set -- $(seq 1 10 | shuf) ; printf '%s, ' "$@" )

เอาท์พุท

5, 9, 7, 2, 4, 3, 6, 1, 10, 8,

แล้วพวกมันก็อยู่ในเปลือกของคุณ

ถ้าคุณได้มันมาในอาร์เรย์ของเชลล์คุณไม่จำเป็นต้องprintf:

( set -- $(seq 1 10 | shuf); IFS=, ; echo "$*" )

เอาท์พุท

9,4,10,3,1,2,7,5,6,8

โดยวิธีการseqและprintfถูกสร้างขึ้นมาเพื่อกันและกัน เช่นถ้าฉันต้องการที่จะทำซ้ำสตริง 1,000 ครั้ง?

printf 'a string\n%.0b' `seq 1 1000`

เอาท์พุท

a string

... 999 a stringสายในภายหลัง ...

a string

หรือ...

printf 'a string,%.0b' `seq 1 10`

เอาท์พุท

a string,a string,a string,a string,a string,a string,a string,a string,a string,a string,

ฉันต้องการรันคำสั่ง 39 ครั้งหรือไม่

printf 'echo "run %d"\n' `seq 1 39` | . /dev/stdin

เอาท์พุท

run 1

... 38 runบรรทัดในภายหลัง ...

run 39


1

POSIXly เพื่อสร้างรายการแบบสับของจำนวนเต็มฐานสิบminถึงmax:

awk -v min=1 -v max=10 'BEGIN{
  for (i = min; i <= max; i++) a[i] = i
  srand()
  for (i = min; i <= max; i++) {
    j = int(rand() * (max - min + 1)) + min
    tmp = a[i]; a[i] = a[j]; a[j] = tmp
  }
  for (i = min; i <= max; i++) print a[i]
}'

ระวังกับการใช้งาน awk จำนวนมากเรียกใช้คำสั่งที่สองครั้งภายในสองเดียวกันจะสร้างผลลัพธ์เดียวกัน (เป็นsrand()เมล็ดกำเนิดสุ่มหลอกขึ้นอยู่กับเวลาปัจจุบัน)

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