Como posso randomizar as linhas em um arquivo usando ferramentas padrão no Red Hat Linux?
Eu não tenho o shuf
comando, então estou procurando por algo como um perl
ou awk
uma linha que realize a mesma tarefa.
Como posso randomizar as linhas em um arquivo usando ferramentas padrão no Red Hat Linux?
Eu não tenho o shuf
comando, então estou procurando por algo como um perl
ou awk
uma linha que realize a mesma tarefa.
Respostas:
E você ganha uma linha de Perl!
perl -MList::Util -e 'print List::Util::shuffle <>'
Ele usa um módulo, mas o módulo faz parte da distribuição de código Perl. Se isso não for bom o suficiente, você pode considerar lançar o seu próprio.
Tentei usar isso com o -i
sinalizador ("editar no local") para que ele edite o arquivo. A documentação sugere que deveria funcionar, mas não funciona. Ele ainda exibe o arquivo embaralhado em stdout, mas desta vez exclui o original. Eu sugiro que você não use.
Considere um script de 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
Não testado, mas espero que funcione.
ruby -e 'puts STDIN.readlines.shuffle'
. Seria necessário testar em grandes entradas para ver se a velocidade é comparável. (também funciona no OS X)
shuf
carrega tudo na memória, por isso não funciona com um arquivo realmente grande (o meu é de aproximadamente 300 GB tsv). Este script perl falhou no meu também, mas sem nenhum erro, exceto Killed
. Alguma ideia se a solução perl está carregando tudo na memória também, ou há algum outro problema que estou encontrando?
Hum, não vamos esquecer
sort --random-sort
brew install coreutils
Todos os utilitários são prefixados com ag so: gsort --random-sort
ou gshuf
funcionarão como esperado
gsort
e gshuf
instalei quando fizport install coreutils
shuf
vez disso (no Linux).
shuf
é a melhor maneira.
sort -R
é dolorosamente lento. Eu apenas tentei classificar o arquivo de 5 GB. Desisti após 2,5 horas. Então shuf
resolveu em um minuto.
sort -R
lentidão é que calcula um hash para cada linha. Dos documentos: " Classifique por hash das chaves de entrada e, em seguida, classificando os valores de hash. "
shuf
carrega tudo na memória.
seq -f 'line %.0f' 1000000
levou o mesmo, muito tempo para processar (muito, muito mais do que com shuf
), não importa quanta memória eu aloquei.
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Leia o arquivo, prefixe cada linha com um número aleatório, classifique o arquivo com esses prefixos aleatórios e corte os prefixos depois. One-liner que deve funcionar em qualquer shell semi-moderno.
EDITAR: incorporou as observações de Richard Hansen.
$RANDOM
), mas -1 para massacrar os dados. Substituir while read f
por while IFS= read -r f
impedirá a read
remoção de espaços em branco à esquerda e à direita (veja esta resposta ) e impedirá o processamento de barras invertidas. Usar uma string aleatória de comprimento fixo impedirá a cut
exclusão de espaços em branco iniciais. Resultado: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Um one-liner para python:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
E para imprimir apenas uma única linha aleatória:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
Mas veja este post para as desvantagens do python random.shuffle()
. Não funcionará bem com muitos (mais de 2080) elementos.
Relacionado à resposta de Jim:
Meu ~/.bashrc
contém o seguinte:
unsort ()
{
LC_ALL=C sort -R "$@"
}
Com GNU coreutils's sort, -R
= --random-sort
, que gera um hash aleatório de cada linha e classifica por ele. O hash aleatório não seria realmente usado em algumas localidades em algumas versões mais antigas (com erros), fazendo com que retornasse a saída classificada normal, que é o motivo pelo qual eu configurei LC_ALL=C
.
Relacionado à resposta de Chris:
perl -MList::Util=shuffle -e'print shuffle<>'
é uma linha ligeiramente mais curta. ( -Mmodule=a,b,c
é uma abreviação de -e 'use module qw(a b c);'
.)
A razão de dar a ele um simples -i
não funciona para embaralhar no local é porque Perl espera que print
aconteça no mesmo loop em que o arquivo está sendo lido, e print shuffle <>
não sai até que todos os arquivos de entrada tenham sido lidos e fechados.
Como uma solução alternativa mais curta,
perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'
irá embaralhar os arquivos no local. ( -n
significa "envolver o código em um while (<>) {...}
loop; BEGIN{undef$/}
faz o Perl operar em arquivos por vez em vez de linhas por vez, e split/^/m
é necessário porque $_=<>
foi feito implicitamente com um arquivo inteiro em vez de linhas.)
O FreeBSD tem seu próprio utilitário aleatório:
cat $file | random | ...
Está em / usr / games / random, portanto, se você não instalou os jogos, está sem sorte.
Você pode considerar a instalação de portas como textproc / rand ou textproc / msort. Eles podem estar disponíveis no Linux e / ou Mac OS X, se a portabilidade for uma preocupação.
No OSX, baixando o mais recente de http://ftp.gnu.org/gnu/coreutils/ e algo como
./configure make sudo make install
... deve fornecer a você / usr / local / bin / sort --random-sort
sem bagunçar / usr / bin / sort
Ou obtenha-o no MacPorts:
$ sudo port install coreutils
e / ou
$ /opt/local//libexec/gnubin/sort --random-sort