Mein Skript erzeugt die gleiche Ausgabe, wenn $ RANDOM verwendet wird

8

Ich versuche, ein zufälliges nBuchstabenwort zu drucken , das ich nüber die Befehlszeile selbst eingebe, aber aus irgendeinem Grund gibt mir mein Skript jedes Mal die gleiche Antwort, wenn ich den gleichen Wert für verwende n.

#!/bin/bash                                                                                                                                       
num=$1
egrep "^.{$num}$" /usr/share/dict/words | head -n $RANDOM| tail -n 1

Ich rufe mein Skript wie folgt auf:

$ bash var3.sh 5
étude             # always the same output when using 5 

$ bash var3.sh 3
zoo               # always the same output when using 3

Wo var3.shist der Name meines Skripts und 5 ist die Länge des Wortes, das ich zufällig drucken möchte.

Wie kann ich ein wirklich zufälliges Wort drucken?

Karan Singh
quelle
3
$RANDOMist ziemlich wahrscheinlich größer als die Anzahl der n- Buchstaben-Wörter für die meisten Werte von n (95,7% der Zeit für n = 3 für mich).
Michael Homer
Möchten Sie ein zufälliges Wort vollständig drucken, auch wenn es kein Wort ist, oder es zufällig aus dem Diktat drucken?
iZodiac
Wenn sich Ihre Aufgabe auf die Sicherheit bezieht (z. B. um ein Kennwort zu erstellen), sollten Sie ein für diese Aufgabe entwickeltes Tool verwenden. Andernfalls ist es möglich, shufoder sort -Rwie in den Antworten vorgeschlagen zu verwenden. Sie können auch verwenden $RANDOM, jedoch auf fortgeschrittenere Weise. Alle diese Tools liefern vorhersagbare Ergebnisse (sie sind nicht wirklich zufällig), aber sie sind schnell und für viele Zwecke gut genug.
Sudodus
1
Vielleicht verwenden sie diese Methode (obligatorische XKCD-Referenz)
Molnarm

Antworten:

20

Das tut es nicht. Aber $ RANDOM gibt große Zahlen zurück (zwischen 0 und 32767), die insbesondere für Wörter mit begrenzter Länge das gleiche Ergebnis zeigen, da der headTeil wahrscheinlich alle Ergebnisse des grep zurückgibt (für 3 gibt es nur 819 Übereinstimmungen in meinem /usr/share/dict/words).

Eine bessere Lösung könnte darin bestehen, die Ergebnisse zu mischen:

egrep "^.{$num}$" /usr/share/dict/words | sort -R | tail -n 1

wo -Rbedeutet --random-sort(eine GNU- sortErweiterung).

Jakub Lucký
quelle
16
Warum tail? Das machte im OP-Skript Sinn, aber da Sie mischen, können Sie es auch verwenden headund sortsollten dann in der Lage sein, das gebrochene Rohr zu erkennen und sich nicht die Mühe zu machen, den Rest der Zeilen zu mischen.
Peter Taylor
@ PeterTaylor wahrscheinlich ein guter Tipp. Schwanz zu benutzen ist nur eine Gewohnheit von mir ... Am Ende würde ich wahrscheinlich noch mehr bevorzugen shuf -n1, was eine Pfeife weniger ist ...
Jakub Lucký
19

Eine einfache Methode , eine beliebige ausdrucken num - Bf Word verwendet shuf:

egrep "^.{$num}$" /usr/share/dict | shuf -n1

Der shufBefehl gibt eine zufällige Permutation der Eingabe aus, und das -n1Flag weist ihn an, nur das erste Element aus diesem Ergebnis auszugeben.

Fuchs
quelle
3
oder grep -Ex ".{$num}". Oder awk 'length == n' n="$num"'.
Stéphane Chazelas
5

Wie andere bereits betont haben, besteht das Hauptproblem bei Ihrem Code darin, dass der $RANDOMWert häufig viel größer ist als die Anzahl der Wörter einer bestimmten Länge.

Mit awknur:

$ awk -v len="$num" 'length == len { word[i++]=$0 }
                     END { print word[int(i*rand())] }' /usr/share/dict/words
Bosniac

Das Programm liest alle Zeilen aus der angegebenen Datei ein, die eine bestimmte Länge haben. Diese werden im Array gespeichert words.

Am Ende wird ein zufälliges Element aus diesem Array ausgewählt und gedruckt.

Kusalananda
quelle