Ich versuche ein Shell-Skript zu schreiben. Die Idee ist, eine einzelne Zeile zufällig aus einer Textdatei auszuwählen und sie als Ubuntu-Desktop-Benachrichtigung anzuzeigen.
Ich möchte jedoch, dass bei jeder Ausführung des Skripts andere Zeilen ausgewählt werden. Gibt es dafür eine Lösung? Ich möchte nicht das gesamte Drehbuch. Nur diese einfache Sache.
scripts
text-processing
Anandu M Das
quelle
quelle
Antworten:
Sie können das
shuf
Dienstprogramm verwenden, um zufällige Zeilen aus einer Datei zu drucken-n
: Anzahl der zu druckenden ZeilenBeispiele:
quelle
n
die Anzahl der zu druckenden Zeilen angeben . (dh ob Sie nur eine Zeile oder zwei Zeilen möchten). Nicht die Zeilennummer (dh erste Zeile 2. Zeile).date +%S
folgt aussieht : Speichere die aktuelle Zeit (nur die Sekunde, von ) in einer Variablen x und wähle dann diese x-te Zeile mit den Befehlenhead
undtail
aus der Textdatei aus. Auf jeden Fall ist Ihre Methode einfacher. Dankeshuf
Befindet sich in coreutils, ist also standardmäßig verfügbar. Hinweis: Die Eingabedatei wird in den Speicher geladen. Es gibt einen effizienten Algorithmus, der dies nicht erfordert .Sie können auch den
sort
Befehl verwenden, um eine zufällige Zeile aus der Datei abzurufen.quelle
sort -R
Erzeugt ein anderes Ergebnis alsshuf -n1
oderselect-random
wenn die Eingabe doppelte Zeilen enthält. Siehe @ EliahKagans Kommentar .Just for fun, hier ist eine reine bash - Lösung , die nicht verwendet
shuf
,sort
,wc
,sed
,head
,tail
oder andere externe Tools.Der einzige Vorteil gegenüber der
shuf
Variante ist, dass es etwas schneller ist, da es reine Bash ist. Auf meinem Computershuf
dauert die Variante für eine Datei mit 1000 Zeilen ungefähr 0,1 Sekunden, während das folgende Skript ungefähr 0,01 Sekunden dauertshuf
.Ganz ehrlich, ich würde mich immer noch für die
shuf
Lösung entscheiden, es sei denn, hohe Effizienz ist ein wichtiges Anliegen.quelle
shuf
ist sowieso viel besser. Wenn ich daran denke, glaube ich nicht, dass reines Bash tatsächlich effizienter ist als das Verwendenshuf
, wie ich zuvor geschrieben habe. Es kann den kleinsten (konstanten) Overhead geben, wenn ein externes Tool gestartet wird, aber dann läuft es mach schneller als interpretierte Bash. Skaliert alsoshuf
sicher besser. Nehmen wir also an, das Drehbuch dient einem pädagogischen Zweck: Es ist schön zu sehen, dass es getan werden kann;)shuf
GNU Coreutils-spezifisch (z. B. nicht in FreeBSD 10.0).sort -R
ist portabel, löst jedoch ein anderes (verwandtes) Problem: Zeichenfolgen, die als mehrere Zeilen angezeigt werden, haben eine Wahrscheinlichkeit, die der Wahrscheinlichkeit entspricht, die nur einmal angezeigt wird. (Natürlichwc
und andere Dienstprogramme könnten noch verwendet werden.) Ich denke, die Haupteinschränkung ist, dass hier niemals etwas nach der 32768-Zeile ausgewählt wird (und etwas früher weniger zufällig wird).$((RANDOM<<15|RANDOM))
ist in 0..2 ^ 30-1. @JFSebastian Es istshuf
nicht sosort -R
, dass es zu häufigeren Eingaben kommt. Anstelleshuf -n 1
von setzensort -R | head -n1
und vergleichen. (Btw 10 ^ 3 Iterationen ist schneller als 10 ^ 6 und noch recht genug , um den Unterschied zu zeigen.) Siehe auch eine rauere, mehr visuelle Demo und dieses Stück silliness zeigt es auf großen Eingängen arbeitet , wo alle Strings Hochfrequenz sind .dieharder
scheint die Eingabe für alle Nullen zu sein. Vorausgesetzt, dies ist nicht nur ein merkwürdiger Fehler von meiner Seite, würde das sicherlich erklären, warum es nicht zufällig ist! Erhalten Sie gut aussehende Daten, wenn Siewhile echo $(( RANDOM << 17 | RANDOM << 2 | RANDOM >> 13 )); do :; done | perl -ne 'print pack "I>"' > out
eine Weile laufen und dann den Inhaltout
mit einem Hex-Editor untersuchen? (Oder sehen Sie es jedoch , was Sie mögen.) Ich Nullen erhalten, undRANDOM
ist nicht der Schuldige: ich alle Nullen, wenn ich ersetzen$(( RANDOM << 17 | RANDOM << 2 | RANDOM >> 13 ))
mit100
, auch.Angenommen, Sie haben eine Datei
notifications.txt
. Wir müssen die Gesamtzahl der Zeilen zählen, um die Reichweite des Zufallsgenerators zu bestimmen:Schreiben wir in die Variable:
Um nun eine Zahl von
0
bis zu generieren , verwenden$LINE
wir eineRANDOM
Variable.Schreiben wir es in die Variable:
Jetzt müssen wir nur noch diese Zeilennummer drucken:
Über RANDOM:
Stellen Sie sicher, dass Ihre Datei weniger als 32767 Zeilennummern hat. Sehen Sie dies, wenn Sie einen größeren Zufallsgenerator benötigen, der sofort einsatzbereit ist.
Beispiel:
quelle
LINES=$(wc -l < file.txt); R_LINE=$((RANDOM % LINES)); sed -n "${R_LINE}p" file.txt
$RANDOM % n
Kann Ihre zufällige Verteilung$RANDOM
% n
, eine Zufallszahl zu verwenden.Hier ist ein Python-Skript, das eine zufällige Zeile aus Eingabedateien oder stdin auswählt:
Der Algorithmus ist O (n) -Zeit, O (1) -Raum. Es funktioniert für Dateien mit mehr als 32767 Zeilen. Eingabedateien werden nicht in den Speicher geladen. Es liest jede Eingabezeile genau einmal, dh, Sie können beliebig große (aber endliche) Inhalte einlesen. Hier ist eine Erklärung des Algorithmus .
quelle
Ich bin beeindruckt von der Arbeit, die Malte Skoruppa und andere geleistet haben, aber hier ist eine viel einfachere "pure bash" -Methode:
Wie einige angemerkt haben, ist $ RANDOM nicht zufällig. Die Dateigrößenbeschränkung von 32767 Zeilen wird jedoch durch Aneinanderreihen von $ RANDOMs nach Bedarf überwunden.
quelle