Come posso randomizzare le righe in un file utilizzando strumenti standard su Red Hat Linux?
Non ho il shuf
comando, quindi sto cercando qualcosa come una riga perl
o awk
una riga che svolga lo stesso compito.
Come posso randomizzare le righe in un file utilizzando strumenti standard su Red Hat Linux?
Non ho il shuf
comando, quindi sto cercando qualcosa come una riga perl
o awk
una riga che svolga lo stesso compito.
Risposte:
E ottieni una battuta in Perl!
perl -MList::Util -e 'print List::Util::shuffle <>'
Usa un modulo, ma il modulo fa parte della distribuzione del codice Perl. Se questo non è abbastanza buono, potresti prendere in considerazione l'idea di rotolare il tuo.
Ho provato a usarlo con il -i
flag ("edit-in-place") per farlo modificare il file. La documentazione suggerisce che dovrebbe funzionare, ma non è così. Visualizza ancora il file mescolato allo stdout, ma questa volta elimina l'originale. Ti suggerisco di non usarlo.
Considera uno script di 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 testato, ma si spera che funzioni.
ruby -e 'puts STDIN.readlines.shuffle'
. Avrebbe bisogno di test su grandi input per vedere se la velocità è comparabile. (funziona anche su OS X)
shuf
carica tutto in memoria, quindi non funziona con un file veramente enorme (il mio è ~ 300 GB tsv). Anche questo script perl è fallito sul mio, ma senza errori tranne Killed
. Qualche idea se la soluzione perl sta caricando tutto anche in memoria, o c'è qualche altro problema che sto riscontrando?
Um, non dimentichiamolo
sort --random-sort
brew install coreutils
tutte le utilità hanno il prefisso ag quindi: gsort --random-sort
o gshuf
funzionerà come previsto
gsort
e gshuf
installato quando l'ho fattoport install coreutils
shuf
invece (su Linux).
shuf
è il modo migliore.
sort -R
è dolorosamente lento. Ho appena provato a ordinare il file da 5 GB. Ho rinunciato dopo 2,5 ore. Quindi shuf
risolto in un minuto.
sort -R
sia lento è che calcola un hash per ogni riga. Dai documenti: " Ordina per hash delle chiavi di input e poi ordina i valori hash. "
shuf
carica tutto in memoria.
seq -f 'line %.0f' 1000000
ha richiesto lo stesso, molto tempo per l'elaborazione (molto, molto più a lungo rispetto a shuf
), indipendentemente dalla quantità di memoria allocata.
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Leggi il file, aggiungi un numero casuale all'inizio di ogni riga, ordina il file su quei prefissi casuali, poi taglia i prefissi. One-liner che dovrebbe funzionare in qualsiasi shell semi-moderna.
EDIT: ha incorporato le osservazioni di Richard Hansen.
$RANDOM
), ma -1 per la macellazione dei dati. La sostituzione while read f
con while IFS= read -r f
impedirà la read
rimozione di spazi bianchi iniziali e finali (vedere questa risposta ) e impedirà l'elaborazione di barre rovesciate. L'uso di una stringa casuale di lunghezza fissa impedirà l' cut
eliminazione degli spazi bianchi iniziali. Risultato: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Una riga di testo per Python:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
E per stampare solo una singola riga casuale:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
Ma guarda questo post per gli svantaggi di Python random.shuffle()
. Non funzionerà bene con molti (più di 2080) elementi.
In relazione alla risposta di Jim:
Il mio ~/.bashrc
contiene quanto segue:
unsort ()
{
LC_ALL=C sort -R "$@"
}
Con l'ordinamento di GNU coreutils, -R
= --random-sort
, che genera un hash casuale di ogni riga e ordina in base ad esso. L'hash randomizzato non sarebbe stato effettivamente utilizzato in alcune versioni locali in alcune versioni precedenti (buggy), causando la restituzione di un normale output ordinato, motivo per cui ho impostato LC_ALL=C
.
In relazione alla risposta di Chris:
perl -MList::Util=shuffle -e'print shuffle<>'
è un one-liner leggermente più corto. ( -Mmodule=a,b,c
è una scorciatoia per-e 'use module qw(a b c);'
.)
Il motivo per cui -i
non funziona per lo shuffling sul posto è perché Perl si aspetta che ciò print
avvenga nello stesso ciclo in cui il file viene letto, eprint shuffle <>
non viene prodotto finché tutti i file di input non sono stati letti e chiusi.
Come soluzione più breve,
perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'
mescolerà i file sul posto. ( -n
significa "avvolgere il codice in un while (<>) {...}
ciclo; BEGIN{undef$/}
fa sì che Perl operi su file alla volta invece che su righe alla volta, ed split/^/m
è necessario perché $_=<>
è stato implicitamente fatto con un intero file invece che con le righe.)
FreeBSD ha la sua utilità casuale:
cat $file | random | ...
È in / usr / games / random, quindi se non hai installato giochi, sei sfortunato.
Potresti considerare l'installazione di porte come textproc / rand o textproc / msort. Questi potrebbero essere disponibili su Linux e / o Mac OS X, se la portabilità è un problema.
Su OSX, prendendo le ultime da http://ftp.gnu.org/gnu/coreutils/ e qualcosa di simile
./configure make sudo make install
... dovrebbe darti / usr / local / bin / sort --random-sort
senza rovinare / usr / bin / sort
Oppure scaricalo da MacPorts:
$ sudo port install coreutils
e / o
$ /opt/local//libexec/gnubin/sort --random-sort