Il utilise un module, mais le module fait partie de la distribution de code Perl. Si ce n'est pas suffisant, vous pouvez envisager de rouler le vôtre.
J'ai essayé de l'utiliser avec le -idrapeau ("edit-in-place") pour qu'il modifie le fichier. La documentation suggère que cela devrait fonctionner, mais ce n'est pas le cas. Il affiche toujours le fichier mélangé vers stdout, mais cette fois, il supprime l'original. Je vous suggère de ne pas l'utiliser.
Considérez un script shell:
#!/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
Pour sauvegarder le fichier d'origine, vous pouvez ajouter
Steve Schnepp
Je suis habituellement un fan Perl, mais suis tombé sur cet exemple de rubis qui a l'avantage d'être plus courte: ruby -e 'puts STDIN.readlines.shuffle'. Il faudrait des tests sur de grosses entrées pour voir si la vitesse est comparable. (fonctionne aussi sur OS X)
mivk
par commentaire ci-dessous, shufcharge tout en mémoire, donc cela ne fonctionne pas avec un fichier vraiment énorme (le mien est ~ 300 Go tsv). Ce script perl a également échoué sur le mien, mais sans erreur sauf Killed. Une idée si la solution perl charge également tout en mémoire, ou y a-t-il un autre problème que je rencontre?
Eh bien, j'utilise gnu-coreutils 7.1 (installation standard de gentoo), qui a un tri avec cette option, je ne sais pas quand elle est apparue, ou si c'est dans d'autres implémentations.
Jim T
1
La fonctionnalité a été validée le 10 décembre 2005, la version suivante était la 5.94, donc je suppose qu'elle est disponible depuis cette version.
Jim T
41
Sur OS X , vous pouvez installer gnu coreutils avec homebrew: brew install coreutilsTous les utils sont préfixées avec ag donc: gsort --random-sortou gshuffonctionnera comme prévu
mike
3
+1 @mike. J'utilise Macports et j'ai aussi eu gsortet gshufinstallé quand je l'ai faitport install coreutils
Noah Sussman
10
Cette solution n'est bonne que si vos lignes n'ont pas de répétitions. Si tel est le cas, toutes les instances de cette ligne apparaîtront les unes à côté des autres. Pensez à utiliser à la shufplace (sous Linux).
Ali J
118
shuf est le meilleur moyen.
sort -Rest douloureusement lent. J'ai juste essayé de trier le fichier de 5 Go. J'ai abandonné après 2,5 heures. Puis shuftrié en une minute.
@benroth: D'après ce que je peux dire, avec un très grand nombre d'entrées, augmenter la mémoire peut aider un peu , mais c'est toujours lent dans l'ensemble. Dans mes tests, le tri d' un fichier d'entrée de 1 million de ligne créée avec seq -f 'line %.0f' 1000000a la même, à long temps de processus (beaucoup, beaucoup plus qu'avec shuf), peu importe la quantité de mémoire que j'alloué.
mklement0
1
@ mklement0, vous avez raison! Je l'ai juste essayé avec un fichier beaucoup plus gros que ce que j'avais auparavant, et le hachage semble être le goulot d'étranglement.
Lisez le fichier, ajoutez un nombre aléatoire à chaque ligne, triez le fichier sur ces préfixes aléatoires, coupez les préfixes par la suite. Une doublure qui devrait fonctionner dans n'importe quelle coque semi-moderne.
EDIT: a incorporé les remarques de Richard Hansen.
Cela fonctionne, et est une solution créative, mais supprimera les espaces de début sur les lignes.
Chris Lutz
@Chris en changeant la dernière coupe en | sed 's / ^ [^ \ t] * \ t //' devrait corriger cela
bdonlan
Bravo à la simplicité de l'approche!
Shashikant Kore
3
+1 pour la conformité POSIX (sauf pour $RANDOM), mais -1 pour le dépeçage des données. Le remplacement while read fpar while IFS= read -r fempêchera readde supprimer les espaces de début et de fin (voir cette réponse ) et empêchera le traitement des contre-obliques. L'utilisation d'une chaîne aléatoire de longueur fixe empêchera cutde supprimer les espaces de début. Résultat: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Richard Hansen du
3
@Richard Hansen: Merci, ces modifications suggérées sont évidemment appropriées, j'ai édité mon message.
Avec le tri de GNU coreutils, -R= --random-sort, qui génère un hachage aléatoire de chaque ligne et trie par elle. Le hachage aléatoire ne serait pas réellement utilisé dans certains paramètres régionaux dans certaines versions plus anciennes (boguées), ce qui le fait renvoyer une sortie triée normale, c'est pourquoi j'ai défini LC_ALL=C.
Lié à la réponse de Chris:
perl -MList::Util=shuffle -e'print shuffle<>'
est une doublure un peu plus courte. ( -Mmodule=a,b,cest un raccourci pour -e 'use module qw(a b c);'.)
La raison pour laquelle donner un simple -ine fonctionne pas pour la lecture aléatoire sur place est que Perl s'attend à ce que cela printse produise dans la même boucle que le fichier est en cours de lecture, et print shuffle <>ne sortira qu'après que tous les fichiers d'entrée aient été lus et fermés.
En guise de solution de contournement plus courte,
va mélanger les fichiers sur place. ( -nsignifie "envelopper le code dans une while (<>) {...}boucle; BEGIN{undef$/}fait en sorte que Perl opère sur des fichiers à la fois au lieu de lignes à la fois, et split/^/mest nécessaire car cela $_=<>a été implicitement fait avec un fichier entier au lieu de lignes.)
Réitérant que le tri -R n'existe pas sous OS X, mais +1 pour quelques bonnes réponses Perl, et une excellente réponse en général.
Chris Lutz
Vous pouvez installer GNU coreutils sur OS X, mais (comme je l'ai fait dans le passé) vous devez faire attention à ne pas casser les outils intégrés ... Cela étant dit, OP est sur Redhat Linux, qui a définitivement GNU norme coreutils.
C'est dans / usr / games / random, donc si vous n'avez pas installé de jeux, vous n'avez pas de chance.
Vous pouvez envisager d'installer des ports tels que textproc / rand ou textproc / msort. Ceux-ci pourraient bien être disponibles sur Linux et / ou Mac OS X, si la portabilité est un problème.
Réponses:
Et vous obtenez un one-liner Perl!
Il utilise un module, mais le module fait partie de la distribution de code Perl. Si ce n'est pas suffisant, vous pouvez envisager de rouler le vôtre.
J'ai essayé de l'utiliser avec le
-i
drapeau ("edit-in-place") pour qu'il modifie le fichier. La documentation suggère que cela devrait fonctionner, mais ce n'est pas le cas. Il affiche toujours le fichier mélangé vers stdout, mais cette fois, il supprime l'original. Je vous suggère de ne pas l'utiliser.Considérez un script shell:
Non testé, mais je l'espère fonctionne.
la source
ruby -e 'puts STDIN.readlines.shuffle'
. Il faudrait des tests sur de grosses entrées pour voir si la vitesse est comparable. (fonctionne aussi sur OS X)shuf
charge tout en mémoire, donc cela ne fonctionne pas avec un fichier vraiment énorme (le mien est ~ 300 Go tsv). Ce script perl a également échoué sur le mien, mais sans erreur saufKilled
. Une idée si la solution perl charge également tout en mémoire, ou y a-t-il un autre problème que je rencontre?Um, n'oublions pas
la source
brew install coreutils
Tous les utils sont préfixées avec ag donc:gsort --random-sort
ougshuf
fonctionnera comme prévugsort
etgshuf
installé quand je l'ai faitport install coreutils
shuf
place (sous Linux).shuf
est le meilleur moyen.sort -R
est douloureusement lent. J'ai juste essayé de trier le fichier de 5 Go. J'ai abandonné après 2,5 heures. Puisshuf
trié en une minute.la source
sort -R
est lente est que calcule un hachage pour chaque ligne. À partir de la documentation: " Trier en hachant les clés d'entrée, puis en triant les valeurs de hachage. "shuf
charge tout en mémoire.seq -f 'line %.0f' 1000000
a la même, à long temps de processus (beaucoup, beaucoup plus qu'avecshuf
), peu importe la quantité de mémoire que j'alloué.Lisez le fichier, ajoutez un nombre aléatoire à chaque ligne, triez le fichier sur ces préfixes aléatoires, coupez les préfixes par la suite. Une doublure qui devrait fonctionner dans n'importe quelle coque semi-moderne.
EDIT: a incorporé les remarques de Richard Hansen.
la source
$RANDOM
), mais -1 pour le dépeçage des données. Le remplacementwhile read f
parwhile IFS= read -r f
empêcheraread
de supprimer les espaces de début et de fin (voir cette réponse ) et empêchera le traitement des contre-obliques. L'utilisation d'une chaîne aléatoire de longueur fixe empêcheracut
de supprimer les espaces de début. Résultat:cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Un one-liner pour python:
Et pour imprimer une seule ligne aléatoire:
Mais voyez cet article pour les inconvénients de python
random.shuffle()
. Cela ne fonctionnera pas bien avec de nombreux éléments (plus de 2080).la source
Lié à la réponse de Jim:
My
~/.bashrc
contient les éléments suivants:Avec le tri de GNU coreutils,
-R
=--random-sort
, qui génère un hachage aléatoire de chaque ligne et trie par elle. Le hachage aléatoire ne serait pas réellement utilisé dans certains paramètres régionaux dans certaines versions plus anciennes (boguées), ce qui le fait renvoyer une sortie triée normale, c'est pourquoi j'ai définiLC_ALL=C
.Lié à la réponse de Chris:
est une doublure un peu plus courte. (
-Mmodule=a,b,c
est un raccourci pour-e 'use module qw(a b c);'
.)La raison pour laquelle donner un simple
-i
ne fonctionne pas pour la lecture aléatoire sur place est que Perl s'attend à ce que celaprint
se produise dans la même boucle que le fichier est en cours de lecture, etprint shuffle <>
ne sortira qu'après que tous les fichiers d'entrée aient été lus et fermés.En guise de solution de contournement plus courte,
va mélanger les fichiers sur place. (
-n
signifie "envelopper le code dans unewhile (<>) {...}
boucle;BEGIN{undef$/}
fait en sorte que Perl opère sur des fichiers à la fois au lieu de lignes à la fois, etsplit/^/m
est nécessaire car cela$_=<>
a été implicitement fait avec un fichier entier au lieu de lignes.)la source
Quand j'installe coreutils avec homebrew
shuf
devient disponible en tant quen
.la source
g
ainsishuf
devenugshuf
pour moi.Mac OS X avec DarwinPorts:
la source
FreeBSD a son propre utilitaire aléatoire:
C'est dans / usr / games / random, donc si vous n'avez pas installé de jeux, vous n'avez pas de chance.
Vous pouvez envisager d'installer des ports tels que textproc / rand ou textproc / msort. Ceux-ci pourraient bien être disponibles sur Linux et / ou Mac OS X, si la portabilité est un problème.
la source
Sur Mac OS X, saisissant des dernières nouvelles de http://ftp.gnu.org/gnu/coreutils/ et quelque chose comme
./configure make sudo make install
... devrait vous donner / usr / local / bin / sort --random-sort
sans gâcher / usr / bin / sort
la source
Ou obtenez-le de MacPorts:
et / ou
la source