Bagaimana cara mengacak output dari seq?


11

Saya tahu saya dapat menggunakan sequntuk menghasilkan daftar angka acak: 1, 2, 3, 4 ...

Saya ingin mendapatkan angka-angka itu dalam urutan acak seperti 3, 1, 4, 2 ...

Saya tahu saya bisa gunakan shufuntuk mengocok baris file. Jadi saya bisa gunakan sequntuk menulis angka acak ke file dan kemudian gunakan shufuntuk mengacaknya - atau menulis semacam fungsi acak. Tapi ini tampaknya tidak perlu rumit. Apakah ada cara yang lebih sederhana untuk mengacak item dalam array dengan satu perintah?

Jawaban:


16

Anda hanya bisa menyalurkan output ke shuf.

$ seq 100 | shuf

Contoh

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

Jika Anda ingin output menjadi horisontal maka pipa itu 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 

Ingin dengan koma di antaranya? Ubah pembatas ke paste:

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

Tetapi Anda harus memformatnya untuk mendapatkan mereka dalam satu baris dengan koma. echo $(seq 10 | shuf)mendekati tetapi tidak melakukan koma.
mikeserv

Itu horisontal sebelum paste...
mikeserv

@ mikeserv - mengubahnya sekitar.
slm

Ya. Ini dia. Saya tidak tahu pastemelakukannya. Terima kasih telah mengajari saya. Dapatkan upvote.
mikeserv

@ mikeserv - ya membaca situs melihat tambang, Stephane atau Gilles A menggunakan joindan paste. Kedua alat itu sangat kuat.
slm

3

Apakah ada cara yang lebih sederhana untuk mengacak item dalam array dengan satu perintah?

Asumsikan Anda memiliki array bilangan desimal:

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

Anda bisa menggunakan printfdan shufmengacak elemen-elemen array:

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

(di atas mengasumsikan Anda belum dimodifikasi $IFS).


Jika semua yang Anda butuhkan adalah angka acak antara dua bilangan bulat, katakan 10dan 20, Anda tidak memerlukan proses tambahan selain shufmenggunakan -iopsi:

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

Mengutip dari man shuf:

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

Kampret. Saya melihat itu juga shuf --helptetapi saya mencoba menggunakan shuf -i 1 10tanpa campur tangan -dash.oh well, kerja bagus - ada baiknya saya.
mikeserv

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

Anda bahkan tidak perlu forloop.

KELUARAN

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

Untuk mendapatkannya dalam shell array yang Anda lakukan:

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

KELUARAN

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

Dan kemudian mereka ada dalam susunan shell Anda.

Jika Anda mendapatkannya di array shell, Anda bahkan tidak perlu printf:

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

KELUARAN

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

Ngomong-ngomong, seqdan printfagak dibuat untuk satu sama lain. Misalnya jika saya ingin mengulang string 1000 kali?

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

KELUARAN

a string

... 999 a stringbaris kemudian ...

a string

Atau...

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

KELUARAN

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

Saya ingin menjalankan perintah 39 kali?

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

KELUARAN

run 1

... 38 runbaris kemudian ...

run 39

1

Anda dapat menggunakan shufperintah untuk mengacak output, misalnya

%> for x in $(seq 1 10 | shuf); do echo -n "$x "; done; echo
4 10 8 7 1 6 3 5 2 9 

1

POSIXly, untuk menghasilkan daftar bilangan bulat desimal dari shuffled minke 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]
}'

Waspadalah bahwa dengan banyak implementasi awk, menjalankan perintah itu dua kali dalam detik yang sama akan menghasilkan hasil yang sama (seperti srand()benih generator pseudo-acak berdasarkan waktu saat ini).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.