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 -isinalizador ("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
Para fazer backup do arquivo original, você pode sufocar uma extensão para o sinalizador -i [ perldoc.perl.org/perlrun.html]
Steve Schnepp
Eu geralmente sou um fã Perl, mas deparei com este exemplo de rubi que tem a vantagem de ser mais curto: 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)
mivk de
por comentário abaixo, shufcarrega 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?
Bem, estou usando o gnu-coreutils 7.1 (instalação padrão do gentoo), que tem classificação com esta opção, não tenho certeza de quando apareceu ou se está em outras implementações.
Jim T
1
O recurso foi lançado em 10 de dezembro de 2005, o lançamento seguinte foi 5.94, então suponho que esteja disponível desde essa versão.
Jim T
41
No OS X você pode instalar gnu coreutils com homebrew: brew install coreutilsTodos os utilitários são prefixados com ag so: gsort --random-sortou gshuffuncionarão como esperado
mike
3
+1 @mike. Eu uso Macports e também tinha gsorte gshufinstalei quando fizport install coreutils
Noah Sussman
10
Esta solução só é boa se suas falas não tiverem repetições. Se o fizerem, todas as instâncias dessa linha aparecerão uma ao lado da outra. Considere usar em shufvez disso (no Linux).
Ali J
118
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 shufresolveu em um minuto.
@benroth: Pelo que eu posso dizer, com contagens de entrada realmente grandes, aumentar a memória pode ajudar um pouco , mas ainda é lento no geral. Em meus testes, classificar um arquivo de entrada de 1 milhão de linhas criado com seq -f 'line %.0f' 1000000levou o mesmo, muito tempo para processar (muito, muito mais do que com shuf), não importa quanta memória eu aloquei.
mklement0
1
@ mklement0, você está certo! Eu apenas tentei com um arquivo muito maior do que o que tinha antes, e o hashing parece ser o gargalo, de fato.
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.
Isso funciona e é uma solução criativa, mas excluirá os espaços em branco iniciais das linhas.
Chris Lutz
@Chris alterando o último corte para | sed 's / ^ [^ \ t] * \ t //' deve corrigir isso
bdonlan
Parabéns pela simplicidade da abordagem!
Shashikant Kore
3
+1 para conformidade POSIX (exceto para $RANDOM), mas -1 para massacrar os dados. Substituir while read fpor while IFS= read -r fimpedirá a readremoçã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 cutexclusã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-
Richard Hansen
3
@Richard Hansen: Obrigado, essas mudanças sugeridas são obviamente apropriadas, eu editei minha postagem.
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 -inão funciona para embaralhar no local é porque Perl espera que printaconteç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.
irá embaralhar os arquivos no local. ( -nsignifica "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.)
Reiterando que o tipo -R não existe no OS X, mas +1 para algumas ótimas respostas Perl, e uma ótima resposta em geral.
Chris Lutz de
Você poderia instalar GNU coreutils no OS X, mas (como eu fiz no passado) você deve ter cuidado para não quebrar as ferramentas embutidas ... Dito isto, OP está no Redhat Linux, que definitivamente tem GNU padrão coreutils.
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.
Respostas:
E você ganha uma linha de Perl!
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:
Não testado, mas espero que funcione.
fonte
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, excetoKilled
. 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
fonte
brew install coreutils
Todos os utilitários são prefixados com ag so:gsort --random-sort
ougshuf
funcionarão como esperadogsort
egshuf
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ãoshuf
resolveu em um minuto.fonte
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 comshuf
), não importa quanta memória eu aloquei.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.
fonte
$RANDOM
), mas -1 para massacrar os dados. Substituirwhile read f
porwhile IFS= read -r f
impedirá aread
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á acut
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:
E para imprimir apenas uma única linha aleatória:
Mas veja este post para as desvantagens do python
random.shuffle()
. Não funcionará bem com muitos (mais de 2080) elementos.fonte
Relacionado à resposta de Jim:
Meu
~/.bashrc
contém o seguinte: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 configureiLC_ALL=C
.Relacionado à resposta de Chris:
é 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 queprint
aconteça no mesmo loop em que o arquivo está sendo lido, eprint shuffle <>
não sai até que todos os arquivos de entrada tenham sido lidos e fechados.Como uma solução alternativa mais curta,
irá embaralhar os arquivos no local. (
-n
significa "envolver o código em umwhile (<>) {...}
loop;BEGIN{undef$/}
faz o Perl operar em arquivos por vez em vez de linhas por vez, esplit/^/m
é necessário porque$_=<>
foi feito implicitamente com um arquivo inteiro em vez de linhas.)fonte
Quando eu instalo coreutils com homebrew
shuf
torna-se disponível comon
.fonte
g
soshuf
tornou - segshuf
para mim.Mac OS X com DarwinPorts:
fonte
O FreeBSD tem seu próprio utilitário aleatório:
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.
fonte
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
fonte
Ou obtenha-o no MacPorts:
e / ou
fonte