Es wird ein Modul verwendet, das Modul ist jedoch Teil der Perl-Codeverteilung. Wenn das nicht gut genug ist, können Sie erwägen, Ihre eigenen zu rollen.
Ich habe versucht, dies mit dem -iFlag ("Edit-in-Place") zu verwenden, damit die Datei bearbeitet wird. Die Dokumentation schlägt vor, dass es funktionieren sollte, aber es funktioniert nicht. Die gemischte Datei wird weiterhin in stdout angezeigt, diesmal wird jedoch das Original gelöscht. Ich schlage vor, Sie verwenden es nicht.
Betrachten Sie ein Shell-Skript:
#!/bin/sh
if [[ $# -eq 0 ]]
then
echo "Usage: $0 [file ...]"
exit 1
fi
for i in "$@"
do
perl -MList::Util -e 'print List::Util::shuffle <>' $i > $i.new
if [[ `wc -c $i` -eq `wc -c $i.new` ]]
then
mv $i.new $i
else
echo "Error for file $i!"
fi
done
Ich bin normalerweise ein Perl-Fan, bin aber auf dieses Rubin-Beispiel gestoßen, das den Vorteil hat, kürzer zu sein : ruby -e 'puts STDIN.readlines.shuffle'. Es müsste an großen Eingängen getestet werden, um festzustellen, ob die Geschwindigkeit vergleichbar ist. (funktioniert auch unter OS X)
Mivk
Laut Kommentar unten wird shufalles in den Speicher geladen, sodass es mit einer wirklich großen Datei nicht funktioniert (meine ist ~ 300 GB tsv). Dieses Perl-Skript ist auch bei mir fehlgeschlagen, aber ohne Fehler außer Killed. Irgendeine Idee, ob die Perl-Lösung auch alles in den Speicher lädt, oder gibt es ein anderes Problem, auf das ich stoße?
Nun, ich verwende gnu-coreutils 7.1 (Standard-Gentoo-Installation), das mit dieser Option sortiert ist. Ich bin mir nicht sicher, wann es angezeigt wurde oder ob es sich um eine andere Implementierung handelt.
Jim T
1
Die Funktion wurde am 10. Dezember 2005 festgeschrieben, die folgende Version war 5.94, ich vermute also, dass sie seit dieser Version verfügbar ist.
Jim T
41
Unter OS X können Sie gnu coreutils mit homebrew installieren: brew install coreutilsAllen Utils wird ag so vorangestellt: gsort --random-sortoder gshufsie funktionieren wie erwartet
mike
3
+1 @mike. Ich benutze Macports und ich hatte gsortund gshufinstallierte es auch, als ich es tatport install coreutils
Noah Sussman
9
Diese Lösung ist nur dann gut, wenn Ihre Zeilen keine Wiederholungen aufweisen. In diesem Fall werden alle Instanzen dieser Zeile nebeneinander angezeigt. Verwenden Sie shufstattdessen (unter Linux).
Ali J
117
shuf ist der beste Weg.
sort -Rist schmerzhaft langsam. Ich habe gerade versucht, 5 GB Datei zu sortieren. Ich gab nach 2,5 Stunden auf. Dann shufsortierte es in einer Minute.
@benroth: Nach allem, was ich sagen kann, kann eine Erhöhung des Speichers bei sehr großen Eingaben etwas helfen , ist aber insgesamt immer noch langsam. In meinen Tests seq -f 'line %.0f' 1000000dauerte das Sortieren einer Eingabedatei mit 1 Million Zeilen, die mit erstellt wurde, dieselbe lange Zeit (viel, viel länger als mit shuf), unabhängig davon, wie viel Speicher ich zugewiesen habe.
mklement0
1
@ mklement0, du hast recht! Ich habe es gerade mit einer viel größeren Datei versucht als zuvor, und das Hashing scheint tatsächlich der Engpass zu sein.
Lesen Sie die Datei, stellen Sie jeder Zeile eine Zufallszahl voran, sortieren Sie die Datei nach diesen zufälligen Präfixen und schneiden Sie die Präfixe anschließend aus. Einzeiler, der in jeder halbmodernen Schale funktionieren sollte.
Dies funktioniert und ist eine kreative Lösung, löscht jedoch führende Leerzeichen in Zeilen.
Chris Lutz
@ Chris, der den letzten Schnitt in | sed 's / ^ [^ \ t] * \ t //'
ändert
Ein großes Lob an die Einfachheit des Ansatzes!
Shashikant Kore
3
+1 für POSIX-Konformität (außer $RANDOM), aber -1 für das Abschlachten der Daten. Durch Ersetzen while read fdurch while IFS= read -r fwird verhindert, readdass führende und nachfolgende Leerzeichen entfernt werden (siehe diese Antwort ) und die Verarbeitung von Backslashes verhindert wird. Durch die Verwendung einer zufälligen Zeichenfolge mit fester Länge wird verhindert, dass cutführende Leerzeichen gelöscht werden. Ergebnis: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Richard Hansen
3
@ Richard Hansen: Danke, diese vorgeschlagenen Änderungen sind offensichtlich angemessen, ich habe meinen Beitrag bearbeitet.
Mit GNU coreutils 'sort, -R= --random-sort, das einen zufälligen Hash jeder Zeile generiert und danach sortiert. Der randomisierte Hash würde in einigen Gebietsschemas in einigen älteren (fehlerhaften) Versionen nicht verwendet, was dazu führt, dass er eine normal sortierte Ausgabe zurückgibt, weshalb ich ihn festgelegt habe LC_ALL=C.
Bezogen auf Chris 'Antwort:
perl -MList::Util=shuffle -e'print shuffle<>'
ist ein etwas kürzerer Einzeiler. ( -Mmodule=a,b,cist eine Abkürzung für-e 'use module qw(a b c);' .)
Der Grund dafür, dass das einfache -iMischen nicht funktioniert, ist, dass Perl erwartet, dass printdies in derselben Schleife geschieht, in der die Datei gelesen wird, undprint shuffle <> erst ausgegeben wird, nachdem alle Eingabedateien gelesen und geschlossen wurden.
mischt Dateien an Ort und Stelle. ( -nbedeutet "den Code in eine while (<>) {...}Schleife einschließen; BEGIN{undef$/}lässt Perl Dateien einzeln anstatt zeilenweise bearbeiten und split/^/mwird benötigt, weil $_=<>implizit mit einer gesamten Datei anstelle von Zeilen gearbeitet wurde.)
Das Wiederholen dieser Sorte -R gibt es unter OS X nicht, aber +1 für einige großartige Perl-Antworten und eine großartige Antwort im Allgemeinen.
Chris Lutz
Sie könnten GNU-Coreutils unter OS X installieren, aber (wie ich es in der Vergangenheit getan habe) müssen Sie darauf achten, die integrierten Tools nicht zu beschädigen ... Abgesehen davon ist OP unter Redhat Linux, das definitiv GNU hat Coreutils Standard.
FreeBSD hat ein eigenes zufälliges Dienstprogramm:
cat $file | random | ...
Es befindet sich in / usr / games / random. Wenn Sie also keine Spiele installiert haben, haben Sie kein Glück.
Sie können Ports wie textproc / rand oder textproc / msort installieren. Diese sind möglicherweise unter Linux und / oder Mac OS X verfügbar, wenn die Portabilität ein Problem darstellt.
Antworten:
Und einen Perl-Einzeiler bekommen Sie!
Es wird ein Modul verwendet, das Modul ist jedoch Teil der Perl-Codeverteilung. Wenn das nicht gut genug ist, können Sie erwägen, Ihre eigenen zu rollen.
Ich habe versucht, dies mit dem
-i
Flag ("Edit-in-Place") zu verwenden, damit die Datei bearbeitet wird. Die Dokumentation schlägt vor, dass es funktionieren sollte, aber es funktioniert nicht. Die gemischte Datei wird weiterhin in stdout angezeigt, diesmal wird jedoch das Original gelöscht. Ich schlage vor, Sie verwenden es nicht.Betrachten Sie ein Shell-Skript:
Ungetestet, funktioniert aber hoffentlich.
quelle
ruby -e 'puts STDIN.readlines.shuffle'
. Es müsste an großen Eingängen getestet werden, um festzustellen, ob die Geschwindigkeit vergleichbar ist. (funktioniert auch unter OS X)shuf
alles in den Speicher geladen, sodass es mit einer wirklich großen Datei nicht funktioniert (meine ist ~ 300 GB tsv). Dieses Perl-Skript ist auch bei mir fehlgeschlagen, aber ohne Fehler außerKilled
. Irgendeine Idee, ob die Perl-Lösung auch alles in den Speicher lädt, oder gibt es ein anderes Problem, auf das ich stoße?Ähm, vergessen wir nicht
quelle
brew install coreutils
Allen Utils wird ag so vorangestellt:gsort --random-sort
odergshuf
sie funktionieren wie erwartetgsort
undgshuf
installierte es auch, als ich es tatport install coreutils
shuf
stattdessen (unter Linux).shuf
ist der beste Weg.sort -R
ist schmerzhaft langsam. Ich habe gerade versucht, 5 GB Datei zu sortieren. Ich gab nach 2,5 Stunden auf. Dannshuf
sortierte es in einer Minute.quelle
sort -R
dafür ist, dass für jede Zeile ein Hash berechnet wird. Aus den Dokumenten: " Sortieren durch Hashing der Eingabetasten und anschließendes Sortieren der Hashwerte. "shuf
lädt alles in den Speicher.seq -f 'line %.0f' 1000000
dauerte das Sortieren einer Eingabedatei mit 1 Million Zeilen, die mit erstellt wurde, dieselbe lange Zeit (viel, viel länger als mitshuf
), unabhängig davon, wie viel Speicher ich zugewiesen habe.Lesen Sie die Datei, stellen Sie jeder Zeile eine Zufallszahl voran, sortieren Sie die Datei nach diesen zufälligen Präfixen und schneiden Sie die Präfixe anschließend aus. Einzeiler, der in jeder halbmodernen Schale funktionieren sollte.
EDIT: Richard Hansens Bemerkungen aufgenommen.
quelle
$RANDOM
), aber -1 für das Abschlachten der Daten. Durch Ersetzenwhile read f
durchwhile IFS= read -r f
wird verhindert,read
dass führende und nachfolgende Leerzeichen entfernt werden (siehe diese Antwort ) und die Verarbeitung von Backslashes verhindert wird. Durch die Verwendung einer zufälligen Zeichenfolge mit fester Länge wird verhindert, dasscut
führende Leerzeichen gelöscht werden. Ergebnis:cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Ein Einzeiler für Python:
Und zum Drucken nur einer einzigen zufälligen Zeile:
Aber siehe diesen Beitrag für die Nachteile von Python
random.shuffle()
. Es funktioniert nicht gut mit vielen (mehr als 2080) Elementen.quelle
Bezogen auf Jims Antwort:
Mein
~/.bashrc
enthält Folgendes:Mit GNU coreutils 'sort,
-R
=--random-sort
, das einen zufälligen Hash jeder Zeile generiert und danach sortiert. Der randomisierte Hash würde in einigen Gebietsschemas in einigen älteren (fehlerhaften) Versionen nicht verwendet, was dazu führt, dass er eine normal sortierte Ausgabe zurückgibt, weshalb ich ihn festgelegt habeLC_ALL=C
.Bezogen auf Chris 'Antwort:
ist ein etwas kürzerer Einzeiler. (
-Mmodule=a,b,c
ist eine Abkürzung für-e 'use module qw(a b c);'
.)Der Grund dafür, dass das einfache
-i
Mischen nicht funktioniert, ist, dass Perl erwartet, dassprint
dies in derselben Schleife geschieht, in der die Datei gelesen wird, undprint shuffle <>
erst ausgegeben wird, nachdem alle Eingabedateien gelesen und geschlossen wurden.Als kürzere Problemumgehung
mischt Dateien an Ort und Stelle. (
-n
bedeutet "den Code in einewhile (<>) {...}
Schleife einschließen;BEGIN{undef$/}
lässt Perl Dateien einzeln anstatt zeilenweise bearbeiten undsplit/^/m
wird benötigt, weil$_=<>
implizit mit einer gesamten Datei anstelle von Zeilen gearbeitet wurde.)quelle
Wenn ich Coreutils mit Homebrew installiere
shuf
wird verfügbar alsn
.quelle
g
so vorangestellt, dass es für mich soshuf
wurdegshuf
.Mac OS X mit DarwinPorts:
quelle
FreeBSD hat ein eigenes zufälliges Dienstprogramm:
Es befindet sich in / usr / games / random. Wenn Sie also keine Spiele installiert haben, haben Sie kein Glück.
Sie können Ports wie textproc / rand oder textproc / msort installieren. Diese sind möglicherweise unter Linux und / oder Mac OS X verfügbar, wenn die Portabilität ein Problem darstellt.
quelle
Unter OSX das Neueste von http://ftp.gnu.org/gnu/coreutils/ und so ähnlich
./configure make sudo make install
... sollte Ihnen / usr / local / bin / sort --random-sort geben
ohne / usr / bin / sort durcheinander zu bringen
quelle
Oder erhalten Sie es von MacPorts:
und / oder
quelle