Comment puis-je randomiser les lignes d'un fichier à l'aide d'outils standard sur Red Hat Linux?
Je n'ai pas la shuf
commande, donc je recherche quelque chose comme un perl
ou awk
une ligne qui accomplit la même tâche.
Comment puis-je randomiser les lignes d'un fichier à l'aide d'outils standard sur Red Hat Linux?
Je n'ai pas la shuf
commande, donc je recherche quelque chose comme un perl
ou awk
une ligne qui accomplit la même tâche.
Réponses:
Et vous obtenez un one-liner Perl!
perl -MList::Util -e 'print List::Util::shuffle <>'
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:
#!/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
Non testé, mais je l'espère fonctionne.
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 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?
Um, n'oublions pas
sort --random-sort
brew install coreutils
Tous les utils sont préfixées avec ag donc: gsort --random-sort
ou gshuf
fonctionnera comme prévu
gsort
et gshuf
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. Puis shuf
trié en une minute.
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'avec shuf
), peu importe la quantité de mémoire que j'alloué.
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
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.
$RANDOM
), mais -1 pour le dépeçage des données. Le remplacement while read f
par while IFS= read -r f
empêchera read
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êchera cut
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:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
Et pour imprimer une seule ligne aléatoire:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
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).
Lié à la réponse de Jim:
My ~/.bashrc
contient les éléments suivants:
unsort ()
{
LC_ALL=C sort -R "$@"
}
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,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 cela print
se 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,
perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'
va mélanger les fichiers sur place. ( -n
signifie "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/^/m
est nécessaire car cela $_=<>
a été implicitement fait avec un fichier entier au lieu de lignes.)
FreeBSD a son propre utilitaire aléatoire:
cat $file | random | ...
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.
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
Ou obtenez-le de MacPorts:
$ sudo port install coreutils
et / ou
$ /opt/local//libexec/gnubin/sort --random-sort