Estou tentando escrever um script de shell. A idéia é selecionar uma única linha aleatoriamente no arquivo de texto e exibi-la como uma notificação da área de trabalho do Ubuntu.
Mas quero que diferentes linhas sejam selecionadas cada vez que executo o script. Existe alguma solução para fazer isso? Eu não quero o script inteiro. Apenas essa coisa simples.
scripts
text-processing
Anandu M Das
fonte
fonte
Respostas:
Você pode usar o
shuf
utilitário para imprimir linhas aleatórias do arquivo-n
: número de linhas para imprimirExemplos:
fonte
n
o número de linhas para imprimir. (ou seja, se você deseja apenas uma linha ou duas linhas). Não é o número da linha (ou seja, primeira linha 2ª linha).date +%S
) em uma variável xe selecione a décima linha usando os comandoshead
etail
do arquivo de texto. De qualquer forma, seu método é mais fácil. Obrigadoshuf
está no coreutils, portanto está disponível por padrão. Nota: carrega o arquivo de entrada na memória. Existe um algoritmo eficiente que não exige isso .Você também pode usar o
sort
comando para obter uma linha aleatória do arquivo.fonte
sort -R
produz resultados diferentesshuf -n1
ouselect-random
se existem linhas duplicadas na entrada. Veja o comentário de @ EliahKagan .Apenas por diversão, aqui está uma solução festa pura que não usa
shuf
,sort
,wc
,sed
,head
,tail
ou quaisquer outras ferramentas externas.A única vantagem sobre a
shuf
variante é que é um pouco mais rápida, já que é pura festa. Na minha máquina, para um arquivo de 1000 linhas, ashuf
variante leva cerca de 0,1 segundos, enquanto o script a seguir leva cerca de 0,01 segundos;) Portanto, emborashuf
seja a variante mais fácil e mais curta, isso é mais rápido.Com toda a honestidade, eu ainda procuraria a
shuf
solução, a menos que alta eficiência seja uma preocupação importante.fonte
shuf
é muito melhor de qualquer maneira. Pensando nisso, não acredito que o bash puro seja realmente mais eficiente do que usarshuf
, como escrevi anteriormente. Pode haver a menor sobrecarga (constante) ao disparar uma ferramenta externa, mas ela executará o mach mais rápido que o bash interpretado. Então,shuf
certamente dimensiona melhor. Então, digamos que o script serve a um propósito educacional: É bom vê-lo pode ser feito;)shuf
é específico para o GNU Coreutils (por exemplo, não no FreeBSD 10.0).sort -R
é portátil, mas resolve um problema diferente (relacionado): cadeias que aparecem como várias linhas têm probabilidade igual àquelas que aparecem apenas uma vez. (É claro,wc
e outros utilitários ainda podem ser usados.) Acho que a principal limitação aqui é que nunca escolhe nada após a linha 32768 (e se torna menos aleatória um pouco antes).$((RANDOM<<15|RANDOM))
está em 0..2 ^ 30-1. @JFSebastian Não éshuf
issosort -R
que distorce as entradas mais frequentes. Coloqueshuf -n 1
no lugarsort -R | head -n1
e compare. (As iterações entre 10 ^ 3 são mais rápidas que 10 ^ 6 e ainda o suficiente para mostrar a diferença.) Veja também uma demonstração mais áspera e visual e esse pouco de bobagem mostrando que funciona em grandes entradas, onde todas as seqüências de caracteres são de alta frequência .dieharder
parece ser todos os zeros. Supondo que isso não seja apenas um erro estranho da minha parte, isso certamente explicaria por que não é aleatório! Você obtém dados de boa aparência se executarwhile echo $(( RANDOM << 17 | RANDOM << 2 | RANDOM >> 13 )); do :; done | perl -ne 'print pack "I>"' > out
por um tempo e depois examinar o conteúdoout
com um editor hexadecimal? (Ou veja como quiser.) Recebo todos os zeros eRANDOM
não sou o culpado: também recebo todos os zeros quando substituo$(( RANDOM << 17 | RANDOM << 2 | RANDOM >> 13 ))
por100
.Digamos que você tenha um arquivo
notifications.txt
. Precisamos contar o número total de linhas, para determinar o intervalo do gerador aleatório:Vamos escrever para a variável:
Agora, para gerar o número de
0
para$LINE
, usaremos aRANDOM
variávelVamos escrevê-lo na variável:
Agora só precisamos imprimir este número de linha:
Sobre a RANDOM:
Verifique se o seu arquivo tem menos de 32767 números de linha. Veja isso se você precisar de um gerador aleatório maior que funcione imediatamente.
Exemplo:
fonte
LINES=$(wc -l < file.txt); R_LINE=$((RANDOM % LINES)); sed -n "${R_LINE}p" file.txt
$RANDOM % n
pode distorcer sua distribuição aleatória, mesmo se$RANDOM
estiver ok% n
a um número aleatório.Aqui está um script Python que seleciona uma linha aleatória dos arquivos de entrada ou stdin:
O algoritmo é tempo O (n), espaço O (1). Ele funciona para arquivos maiores que 32767 linhas. Não carrega arquivos de entrada na memória. Ele lê cada linha de entrada exatamente uma vez, ou seja, você pode canalizar conteúdo arbitrário (mas finito). Aqui está uma explicação do algoritmo .
fonte
Estou impressionado com o trabalho que Malte Skoruppa e outros fizeram, mas aqui está uma maneira muito mais simples de "festança pura":
Como alguns observaram, $ RANDOM não é aleatório. No entanto, o limite de tamanho do arquivo de 32767 linhas é superado ao juntar $ RANDOMs conforme necessário.
fonte