Respostas:
Não há um recurso interno para isso, então você precisará usar algo externo.
/bin/sh
)A ligar:
strings -n 1 < /dev/urandom | tr -d '[:space:]' | head -c15
com system()
é um bom caminho. Você pode obter apenas números substituindo tr
por grep
:
strings -n 1 < /dev/urandom | grep -o '[[:digit:]]' | head -c15
Você pode usar isso no Vim assim:
:echo system("strings -n 1 < /dev/urandom | grep -o '[[:digit:]]' | head -c15")
O número 15 é a quantidade de números que você deseja (ajuste de acordo). Isso deve funcionar no Linux, BSD, OSX e outros sistemas UNIX. Não vai funcionar no MS Windows.
Veja também o meu blog " Gerar senhas a partir da linha de comando " (existem muitas soluções ruins para isso).
Ruby é provavelmente a próxima melhor opção, pois os scripts Ruby parecem ser um pouco mais comuns que os scripts Python. Obter um número aleatório é fácil:
:ruby puts Random.rand(10)
Ou para obter 15 números:
:ruby 15.times { puts Random.rand(10) }
Você pode usar o módulo aleatório ; para obter um único número:
:py import random; print(random.randint(0, 9))
Ou 15 números:
:py import random
:py for i in range(0, 15): print(random.randint(0, 9))
Isso deve funcionar para o Python 2 e 3.
Você pode usar Get-Random
para obter um número aleatório:
:echo system('Get-Random')
cmd.exe
O Windows 7 e posterior devem ser fornecidos com o PowerShell, mas se você quiser compatibilidade máxima, poderá usá-lo cmd.exe
. Tem uma variável especial %RANDOM%
:
:echo system('@echo %RANDOM%')
Nota: Isso não é muito aleatório! , usa o tempo (!)
Observe que você não precisa usar as ligações Ruby ou Python para usar as soluções Ruby ou Python; você também pode criar um script separado e chamá-lo com
system("python -c '...'")
(isso requer que o ruby / python esteja instalado, obviamente.
tr -d '[:space:]'
, talvez tr -cd '[:digit:]'
para o filtro grep?
:r! hexdump -n $((3*4)) -e '"%d"' /dev/urandom
, geraria 3 números inteiros assinados aleatoriamente.
:r! hexdump -n $((3*4)) -e '"\%d\n"' /dev/urandom
Aqui está uma solução pura para vimscript . Eu não o criei, ele foi desenvolvido por Charles E. Campbell. Você pode encontrar um repositório do Github com seu código aqui .
O algoritmo usa 3 sementes geradas na inicialização do Vim e gera um número pseudo-aleatório com base nos cálculos e permutações aplicados às sementes:
" Randomization Variables
" with a little extra randomized start from localtime()
let g:rndm_m1 = 32007779 + (localtime()%100 - 50)
let g:rndm_m2 = 23717810 + (localtime()/86400)%100
let g:rndm_m3 = 52636370 + (localtime()/3600)%100
O escopo das variáveis é declarado como global porque é usado pela função do gerador, mas pode ser restrito ao script ( s:
)
E aqui está a função do gerador:
function! Rndm()
let m4= g:rndm_m1 + g:rndm_m2 + g:rndm_m3
if( g:rndm_m2 < 50000000 )
let m4= m4 + 1357
endif
if( m4 >= 100000000 )
let m4= m4 - 100000000
if( m4 >= 100000000 )
let m4= m4 - 100000000
endif
endif
let g:rndm_m1 = g:rndm_m2
let g:rndm_m2 = g:rndm_m3
let g:rndm_m3 = m4
return g:rndm_m3
endfun
O repo inclui as seguintes funções:
Aqui está um teste rápido que escrevi para testar o gerador: gerei 1000000 números entre 0 e 9 e contei o número de ocorrências de cada número. Aqui estão os resultados:
0 : 100409
1 : 99435
2 : 100433
3 : 99578
4 : 100484
5 : 99948
6 : 100394
7 : 99649
8 : 99803
9 : 99867
Como você pode ver, a geração parece estar bem distribuída. Estou ciente de que isso não é suficiente para testar um gerador aleatório, então tentarei fazer uma análise extra se tiver algum tempo livre.
Este é um método encontrado no plug - in vim-randomtag , baseado na leitura ... microssegundos para o horário atual, utilizável quando você deseja apenas um número, não se importa muito com a qualidade da aleatoriedade ou se preocupa com a segurança, etc .:
function! s:randnum(max) abort
return str2nr(matchstr(reltimestr(reltime()), '\v\.@<=\d+')[1:]) % a:max
endfunction
O Vim não oferece gerador aleatório nativo; no entanto, se você tiver o vim compilado com Python, o método a seguir anexará um dígito aleatório no final da sua linha:
:py import vim, random; vim.current.line += str(random.randint(0, 9))
Nota: Para verificar se o seu vim suporta Python, tente: :echo has('python')
(1 para sim).
Você também pode usar o shell que oferece $RANDOM
variável (funciona com bash / ksh / zsh) que retorna um pseudo-aleatório (0-32767), por exemplo:
:r! echo $RANDOM
ou:
:put =system('echo $RANDOM')
ou:
:r! od -An -td -N1 /dev/urandom
No Windows, você deve ter o Cygwin / MSYS / SUA instalado ou usar a %RANDOM%
variável conforme sugerido por Carpetsmoker .
Se você não tem acesso ao shell e ao Python, como solução alternativa, use os últimos dígitos do carimbo de data / hora atual, por exemplo:
:put =reltimestr(reltime())[-2:]
Nota: Se você o estiver usando com bastante frequência, escreva uma função simples que sim return reltimestr(reltime())[-4:]
.
Nota: Os métodos acima retornam apenas um número inteiro pseudoaleatório que não deve ser usado para gerar uma chave de criptografia.
Para adicionar mais números aleatórios, pressione @:para repetir o comando novamente. Ou prefixe com number (like 10@:) para adicionar muito mais números aleatórios separados por novas linhas.
Palavras-chave:
zsh
, mas não com sh
, dash
, fish
, csh
, ou tcsh
... Você pode usar :r! bash -c 'echo $RANDOM'
...
GetRandom()
função onde a boa impressão é importante, por isso é melhor acertar desde o início, se possível (e quase sempre é possível aqui!)
$RANDOM
, mas se esse é um PRNG ruim, não é uma razão para usar um PRNG ainda mais pobre :-) Em vez disso, atualize para um PRNG melhor! Tanto quanto eu sei, /dev/urandom
está disponível em todas as plataformas onde bash
está comumente disponível, então não vejo um motivo para não usá-lo.
$RANDOM
. Parece uma pequena ferramenta muito boa, e mesmo que seja um "RNG do pobre" (como aponta a @Carpetsmoker), definitivamente se encaixa no requisito de "facilmente memorável" do @ kenorb (que fez a pergunta).
Você pode usar as funções rand()
e srand()
, desde que o seu binário Vim inclua o patch 8.1.2342 .
Como exemplo, para gerar 10 números aleatórios separados por novas linhas:
let seed = srand()
echo range(10)->map({-> rand(g:seed)})->join("\n")
Para gerar 10 números aleatórios, todos inferiores a 100:
let seed = srand()
echo range(10)->map({-> rand(g:seed) % 100})->join("\n")
Para gerar 10 seqüências alfabéticas aleatórias de 5 caracteres:
let seed = srand()
echo range(10)
\ ->map({-> range(5)
\ ->map({-> (97+rand(g:seed) % 26)->nr2char()})->join('')})
\ ->join("\n")
Para gerar 10 palavras aleatórias (extraídas do arquivo do dicionário /usr/share/dict/words
):
let seed = srand()
let words = readfile('/usr/share/dict/words')
let len = len(words)
echo range(10)->map({-> g:words[rand(g:seed) % g:len]})->join("\n")
Para gerar 10 sequências de 5 palavras aleatórias:
let seed = srand()
let words = readfile('/usr/share/dict/words')
let len = len(words)
echo range(10)
\ ->map({-> range(5)
\ ->map({-> g:words[rand(g:seed) % g:len]})->join()})
\ ->join("\n")
Para gerar uma versão UUID aleatória 4:
" Based on this answer: /programming//a/38191078/9780968
let seed = srand()
let random_numbers = range(30)->map({-> rand(g:seed) % 16})
echo call('printf', ['%x%x%x%x%x%x%x%x-%x%x%x%x-4%x%x%x'] + random_numbers[:14])
\ ..call('printf', ['-X%x%x%x-%x%x%x%x%x%x%x%x%x%x%x%x'] + random_numbers[15:])
\ ->substitute('X', '89ab'[rand(seed) % 4], '')
Para aplicar um esquema de cores aleatório:
let seed = srand()
let colorschemes = getcompletion('', 'color')
let len = colorschemes->len()
exe 'colo '..colorschemes[rand(seed) % len]
Eu não acho que exista uma função nativa para números aleatórios no Vimscript.
Uma maneira de usar :python
(use-o em uma função, talvez, com 10000 e 60 substituídos por parâmetros):
:python <<EOF
import vim
import random
line = vim.current.window.cursor[0]
r = getattr(__builtins__, 'xrange', range) # To make it work for both Python 2 & 3
vim.current.buffer[line:line] = list(map(str, random.sample(r(10000), 60)))
EOF
Veja minha resposta para Criando uma caixa no vim via python para uma rápida introdução sobre scripts em Python no Vim.
Como vim.current.buffer
é uma lista de cadeias de caracteres, podemos atribuir uma lista de cadeias de caracteres da mesma maneira que atribuiríamos no Python. random.sample
é apenas a maneira mais simples de obter uma lista de números inteiros aleatórios em Python.
random.sample
exige apenas dois argumentos no Python 2, str
é a função interna de converter coisas em strings. Deixe-me procurar os equivalentes Py3 ( str
seria o mesmo, terá que verificar xrange
e random.sample
).
xrange
não está no Python3 porque range
é equivalente (nem na verdade constrói uma lista, ao contrário range
do Py2).
map
em PY3 retorna um iterável e não uma lista, para a última linha usarialist(map(str, random.sample(range(10000), 60)))
:python
?