Respuestas:
No hay una función integrada para esto, por lo que deberá usar algo externo.
/bin/sh
)Vocación:
strings -n 1 < /dev/urandom | tr -d '[:space:]' | head -c15
con system()
es una buena manera. Solo puede obtener números reemplazándolos tr
con grep
:
strings -n 1 < /dev/urandom | grep -o '[[:digit:]]' | head -c15
Puedes usar esto en Vim así:
:echo system("strings -n 1 < /dev/urandom | grep -o '[[:digit:]]' | head -c15")
El número 15 es la cantidad de números que desea (ajuste en consecuencia). Esto debería funcionar en Linux, BSD, OSX y otros sistemas UNIX. No funcionará en MS Windows.
También vea mi publicación en el blog " Generar contraseñas desde la línea de comandos " (hay muchas soluciones malas para esto).
Ruby es probablemente la siguiente mejor opción, ya que las secuencias de comandos de Ruby parecen ser un poco más comunes que las de Python. Obtener un número aleatorio es fácil:
:ruby puts Random.rand(10)
O para obtener 15 números:
:ruby 15.times { puts Random.rand(10) }
Puedes usar el módulo aleatorio ; para obtener un solo número:
:py import random; print(random.randint(0, 9))
O un 15 números:
:py import random
:py for i in range(0, 15): print(random.randint(0, 9))
Esto debería funcionar para Python 2 y 3.
Puedes usar Get-Random
para obtener un número aleatorio:
:echo system('Get-Random')
cmd.exe
Windows 7 y versiones posteriores deben enviarse con PowerShell, pero si desea la máxima compatibilidad, puede usarlas cmd.exe
. Tiene una variable especial %RANDOM%
:
:echo system('@echo %RANDOM%')
Nota: ¡ Esto no es muy aleatorio! , usa el tiempo (!)
Tenga en cuenta que no necesita usar los enlaces Ruby o Python para usar las soluciones Ruby o Python; también podría crear un script separado y llamarlos con
system("python -c '...'")
(esto requiere que ruby / python esté instalado, obviamente).
tr -d '[:space:]'
, tal vez tr -cd '[:digit:]'
para el filtro grep?
:r! hexdump -n $((3*4)) -e '"%d"' /dev/urandom
, generaría 3 enteros con signo aleatorio.
:r! hexdump -n $((3*4)) -e '"\%d\n"' /dev/urandom
Aquí hay una solución vimscript pura . No lo creé, fue desarrollado por Charles E. Campbell. Puede encontrar un repositorio de Github con su código aquí .
El algoritmo utiliza 3 semillas generadas en el inicio de Vim y genera un número pseudoaleatorio basado en cálculos y permutaciones aplicadas a las semillas:
" 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
El alcance de las variables se declara como global porque son utilizadas por la función del generador pero podrían estar restringidas al script ( s:
)
Y aquí está la función del generador:
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
El repositorio incluye las siguientes funciones:
Aquí hay una prueba rápida que escribí para probar el generador: generé 1000000 números entre 0 y 9 y conté el número de ocurrencias de cada número, aquí están los resultados:
0 : 100409
1 : 99435
2 : 100433
3 : 99578
4 : 100484
5 : 99948
6 : 100394
7 : 99649
8 : 99803
9 : 99867
Como puede ver, la generación parece estar bien distribuida. Soy consciente de que esto no es suficiente para probar un generador aleatorio, así que intentaré hacer un análisis adicional si tengo algo de tiempo libre.
Este es un método que se encuentra en el complemento vim-randomtag , que se basa en la lectura ... microsegundos de tiempo actual, utilizable cuando solo desea un número, no le importa mucho la calidad de la aleatoriedad o tiene problemas de seguridad, etc.
function! s:randnum(max) abort
return str2nr(matchstr(reltimestr(reltime()), '\v\.@<=\d+')[1:]) % a:max
endfunction
Vim no ofrece un generador aleatorio nativo, sin embargo, si ha compilado vim con Python, el siguiente método agregará un dígito aleatorio al final de su línea:
:py import vim, random; vim.current.line += str(random.randint(0, 9))
Nota: Para verificar si su vim es compatible con Python, intente: :echo has('python')
(1 para sí).
También puedes usar shell que ofrece $RANDOM
variables (funciona con bash / ksh / zsh) que devuelve un pseudoaleatorio (0-32767), por ejemplo:
:r! echo $RANDOM
o:
:put =system('echo $RANDOM')
o:
:r! od -An -td -N1 /dev/urandom
En Windows, debe tener instalado Cygwin / MSYS / SUA, o utilizar %RANDOM%
variables como sugirió Carpetsmoker .
Si no tiene acceso a Shell y Python, como solución alternativa, use los últimos dígitos de la marca de tiempo actual, por ejemplo:
:put =reltimestr(reltime())[-2:]
Nota: Si lo usa con bastante frecuencia, escriba una función simple que return reltimestr(reltime())[-4:]
.
Nota: Los métodos anteriores devuelven solo un entero pseudoaleatorio que no debe usarse para generar una clave de cifrado.
Para agregar más números aleatorios, presione @:para repetir el comando nuevamente. O prefijo con número (como10@: ) para agregar muchos más números aleatorios separados por nuevas líneas.
Relacionado:
zsh
, pero no con sh
, dash
, fish
, csh
, o tcsh
... Usted podría utilizar :r! bash -c 'echo $RANDOM'
...
GetRandom()
función en la que buena PRNG hace la materia, por lo que es mejor simplemente hacer las cosas bien desde el principio, si es posible (y es casi siempre es posible aquí!)
$RANDOM
, pero si este es un PRNG pobre, entonces esa no es una razón para usar un PRNG aún más pobre :-) En su lugar, ¡actualice a un PRNG mejor! Hasta donde sé, /dev/urandom
está disponible en todas las plataformas donde bash
está comúnmente disponible, por lo que no veo una razón para no usarlo.
$RANDOM
. Parece una pequeña herramienta muy agradable, y aunque puede ser un "RNG de hombre pobre" (como señala @Carpetsmoker), definitivamente se ajusta al requisito de "kenorb (que hizo la pregunta) de" fácilmente memorable ".
Puede usar las funciones rand()
y srand()
, siempre que su binario Vim incluya el parche 8.1.2342 .
Como ejemplo, para generar 10 números aleatorios separados por nuevas líneas:
let seed = srand()
echo range(10)->map({-> rand(g:seed)})->join("\n")
Para generar 10 números aleatorios todos inferiores a 100:
let seed = srand()
echo range(10)->map({-> rand(g:seed) % 100})->join("\n")
Para generar 10 cadenas alfabéticas aleatorias de 5 caracteres:
let seed = srand()
echo range(10)
\ ->map({-> range(5)
\ ->map({-> (97+rand(g:seed) % 26)->nr2char()})->join('')})
\ ->join("\n")
Para generar 10 palabras al azar (tomadas del archivo del diccionario /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 generar 10 secuencias de 5 palabras al azar:
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 generar un UUID aleatorio versión 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 un esquema de color aleatorio:
let seed = srand()
let colorschemes = getcompletion('', 'color')
let len = colorschemes->len()
exe 'colo '..colorschemes[rand(seed) % len]
No creo que haya una función nativa para números aleatorios en Vimscript.
Una forma de usar :python
(usarlo en una función, tal vez, con 10000 y 60 reemplazados 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
Vea mi respuesta a Hacer un cuadro en vim a través de python para una introducción rápida sobre las secuencias de comandos de Python en Vim.
Como vim.current.buffer
es una lista de cadenas, podemos asignarle una lista de cadenas de la misma forma que lo haríamos en Python. random.sample
es la forma más simple en que puedo pensar para obtener una lista de enteros aleatorios en Python.
random.sample
tiene solo dos argumentos en Python 2, str
es la función integrada para convertir cosas en cadenas. Permítanme buscar los equivalentes de Py3 ( str
sería lo mismo, tendré que verificar xrange
y random.sample
).
xrange
no está en Python3 porque range
es equivalente (ninguno construye una lista, a diferencia range
de Py2).
map
en Py3 devuelve un iterable y no una lista, por lo que la última línea usaríalist(map(str, random.sample(range(10000), 60)))
:python
?