Wie randomisiere ich die Ausgabe von seq?

11

Ich weiß, dass ich damit seqeine zufällige Liste von Zahlen erstellen kann: 1, 2, 3, 4 ...

Ich möchte diese Zahlen in eine zufällige Reihenfolge wie 3, 1, 4, 2 bringen ...

Ich weiß, dass ich damit shufdie Zeilen einer Datei mischen kann. Ich könnte also seqZufallszahlen in eine Datei schreiben und sie dann shufmischen - oder eine Art Zufallsfunktion schreiben. Dies scheint jedoch unnötig komplex zu sein. Gibt es eine einfachere Möglichkeit, die Elemente in einem Array mit einem einzigen Befehl zufällig zu sortieren?

bernie2436
quelle

Antworten:

16

Sie können die Ausgabe einfach an weiterleiten shuf.

$ seq 100 | shuf

Beispiel

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

Wenn Sie möchten, dass die Ausgabe horizontal ist, leiten Sie sie an weiter 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 

Willst du es mit Kommas dazwischen? Ändern Sie das Trennzeichen in paste:

$ seq 10 | shuf | paste - -s -d ','
2,4,9,1,8,7,3,5,10,6
slm
quelle
Aber du musst irgendwie formatieren, um sie mit Kommas in eine Zeile zu bringen. echo $(seq 10 | shuf)kommt nahe, macht aber keine Kommas.
Mikeserv
Es ist horizontal vor paste...
mikeserv
@mikeserv - hat es geändert.
slm
Ja. Los geht's. Ich wusste pastenicht, dass ich das getan habe. Danke, dass du mich unterrichtet hast. Habe eine Gegenstimme.
Mikeserv
@mikeserv - Ja, lesen Sie die Seite durch und sehen Sie sich entweder meine, Stephanes oder Gilles A's mit joinund an paste. Diese 2 Werkzeuge sind extrem leistungsfähig.
slm
3

Gibt es eine einfachere Möglichkeit, die Elemente in einem Array mit einem einzigen Befehl zufällig zu sortieren?

Angenommen, Sie haben ein Array von Dezimalzahlen:

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

Sie können die Elemente des Arrays verwenden printfund shufzufällig sortieren:

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

(oben wird davon ausgegangen, dass Sie nicht geändert haben $IFS).


Wenn Sie nur Zufallszahlen zwischen zwei Ganzzahlen benötigen, z. B. 10und 20, benötigen Sie keine zusätzlichen Prozesse außer shufder Verwendung der folgenden -iOption:

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

Zitat aus man shuf:

   -i, --input-range=LO-HI
          treat each number LO through HI as an input line
devnull
quelle
Shucks. Ich habe das auch in gesehen, shuf --helpaber ich habe versucht, shuf -i 1 10ohne die Intervention zu verwenden -dash., na ja, gute Arbeit - habe meine Gegenstimme.
Mikeserv
2
printf '%s, ' `seq 1 10 | shuf`

Sie brauchen nicht einmal eine forSchleife.

AUSGABE

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

Um sie in ein Shell-Array zu bekommen, gehen Sie wie folgt vor:

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

AUSGABE

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

Und dann sind sie in Ihrem Shell-Array.

Wenn Sie sie in das Shell-Array aufnehmen, benötigen Sie nicht einmal printf:

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

AUSGABE

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

Übrigens seqund printfsind irgendwie füreinander gemacht. Zum Beispiel, wenn ich eine Zeichenfolge 1000 Mal wiederholen möchte?

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

AUSGABE

a string

... 999 a stringZeilen später ...

a string

Oder...

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

AUSGABE

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

Ich möchte 39 Mal einen Befehl ausführen?

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

AUSGABE

run 1

... 38 runZeilen später ...

run 39
mikeserv
quelle
1

Sie können den shufBefehl verwenden, um die Ausgabe zufällig zu sortieren, z

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

POSIXly, um eine gemischte Liste der Dezimalzahlen von minbis zu generieren 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]
}'

Beachten Sie, dass bei vielen awk-Implementierungen das zweimalige Ausführen dieses Befehls innerhalb derselben Sekunde das gleiche Ergebnis liefert (als srand()Startwert für den Pseudozufallsgenerator basierend auf der aktuellen Zeit).

Stéphane Chazelas
quelle