Réponses:
Il n'y a pas de fonction intégrée pour cela, vous devrez donc utiliser quelque chose d'extérieur.
/bin/sh
)Appel:
strings -n 1 < /dev/urandom | tr -d '[:space:]' | head -c15
avec system()
est un bon moyen. Vous ne pouvez obtenir que des chiffres en les remplaçant tr
par grep
:
strings -n 1 < /dev/urandom | grep -o '[[:digit:]]' | head -c15
Vous pouvez utiliser ceci dans Vim comme ceci:
:echo system("strings -n 1 < /dev/urandom | grep -o '[[:digit:]]' | head -c15")
Le nombre 15 est le nombre de nombres que vous souhaitez (ajustez en conséquence). Cela devrait fonctionner sur Linux, BSD, OSX et d'autres systèmes UNIX. Cela ne fonctionnera pas sur MS Windows.
Voir également mon article de blog " Générer des mots de passe à partir de la ligne de commande " (il existe de nombreuses mauvaises solutions pour cela).
Ruby est probablement le deuxième meilleur choix, car les scripts Ruby semblent être un peu plus courants que les scripts Python. Obtenir un nombre aléatoire est facile:
:ruby puts Random.rand(10)
Ou pour obtenir 15 numéros:
:ruby 15.times { puts Random.rand(10) }
Vous pouvez utiliser le module aléatoire ; pour obtenir un numéro unique:
:py import random; print(random.randint(0, 9))
Ou 15 numéros:
:py import random
:py for i in range(0, 15): print(random.randint(0, 9))
Cela devrait fonctionner pour Python 2 et 3.
Vous pouvez utiliser Get-Random
pour obtenir un nombre aléatoire:
:echo system('Get-Random')
cmd.exe
Windows 7 et versions ultérieures devraient être livrés avec PowerShell, mais si vous souhaitez une compatibilité maximale, vous pouvez utiliser cmd.exe
. Il a une variable spéciale %RANDOM%
:
:echo system('@echo %RANDOM%')
Remarque: ce n'est pas très aléatoire! , il utilise le temps (!)
Notez que vous n'avez pas besoin d'utiliser les liaisons Ruby ou Python pour utiliser les solutions Ruby ou Python; vous pouvez également créer un script séparé et les appeler avec
system("python -c '...'")
(cela nécessite évidemment l'installation de ruby / python.
tr -d '[:space:]'
, peut-être tr -cd '[:digit:]'
pour le filtre grep?
:r! hexdump -n $((3*4)) -e '"%d"' /dev/urandom
-à- dire générer 3 entiers signés aléatoires.
:r! hexdump -n $((3*4)) -e '"\%d\n"' /dev/urandom
Voici une solution Vimscript pure . Je ne l'ai pas créé, il a été développé par Charles E. Campbell. Vous pouvez trouver un dépôt Github avec son code ici .
L'algorithme utilise 3 graines générées au démarrage de Vim et génère un nombre pseudo-aléatoire basé sur des calculs et permutations appliqués aux graines:
" 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
La portée des variables est déclarée globale car elle est utilisée par la fonction générateur mais elle peut être limitée au script ( s:
)
Et voici la fonction générateur:
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
Le dépôt comprend les fonctions suivantes:
Voici un test rapide que j'ai écrit pour tester le générateur: j'ai généré 1000000 nombres entre 0 et 9 et compté le nombre d'occurrences de chaque nombre voici les résultats:
0 : 100409
1 : 99435
2 : 100433
3 : 99578
4 : 100484
5 : 99948
6 : 100394
7 : 99649
8 : 99803
9 : 99867
Comme vous pouvez le voir, la génération semble bien répartie. Je suis conscient que ce n'est largement pas suffisant pour tester un générateur aléatoire, je vais donc essayer de faire une analyse supplémentaire si j'ai du temps libre.
Il s'agit d'une méthode trouvée dans le plugin vim-randomtag , qui est basée sur la lecture ... microsecondes de l'heure actuelle, utilisable lorsque vous voulez juste un certain nombre, vous ne vous souciez pas beaucoup de la qualité de l'aléatoire, ou avez des problèmes de sécurité, etc.:
function! s:randnum(max) abort
return str2nr(matchstr(reltimestr(reltime()), '\v\.@<=\d+')[1:]) % a:max
endfunction
Vim n'offre pas de générateur aléatoire natif, cependant si vous avez compilé vim avec Python, la méthode suivante ajoutera un chiffre aléatoire à la fin de votre ligne:
:py import vim, random; vim.current.line += str(random.randint(0, 9))
Remarque: Pour vérifier si votre vim prend en charge Python, essayez: :echo has('python')
(1 pour oui).
Vous pouvez également utiliser un shell qui offre une $RANDOM
variable (fonctionne avec bash / ksh / zsh) qui renvoie un pseudo-aléatoire (0-32767), par exemple:
:r! echo $RANDOM
ou:
:put =system('echo $RANDOM')
ou:
:r! od -An -td -N1 /dev/urandom
Sous Windows, vous devez avoir installé Cygwin / MSYS / SUA ou utiliser une %RANDOM%
variable comme le suggère Carpetsmoker .
Si vous n'avez pas accès au shell et à Python, comme pour la solution de contournement, vous utilisez les derniers chiffres de l'horodatage actuel, par exemple:
:put =reltimestr(reltime())[-2:]
Remarque: Si vous l'utilisez assez souvent, écrivez une fonction simple qui le fera return reltimestr(reltime())[-4:]
.
Remarque: les méthodes ci-dessus ne renvoient qu'un entier pseudo-aléatoire qui ne doit pas être utilisé pour générer une clé de chiffrement.
Pour ajouter d'autres nombres aléatoires, appuyez sur @:pour répéter la commande à nouveau. Ou préfixez avec un nombre (comme 10@:) pour ajouter beaucoup plus de nombres aléatoires séparés par de nouvelles lignes.
En relation:
zsh
, mais pas avec sh
, dash
, fish
, csh
ou tcsh
... vous pouvez utiliser :r! bash -c 'echo $RANDOM'
...
GetRandom()
fonction là où un bon prng est important, il est donc préférable de le faire dès le début si possible (et c'est presque toujours possible ici!)
$RANDOM
, mais si c'est un mauvais PRNG alors ce n'est pas une raison pour utiliser un PRNG encore plus pauvre :-) Au lieu de cela, passez à un meilleur PRNG! Pour autant que je sache, /dev/urandom
est disponible sur toutes les plates-formes où il bash
est couramment disponible, donc je ne vois pas de raison de ne pas l' utiliser.
$RANDOM
. Cela semble être un très bon petit outil, et même s'il peut s'agir d'un "pauvre homme RNG" (comme le souligne @Carpetsmoker), il correspond certainement à l'exigence de "facilement mémorisable" de @ kenorb (qui a posé la question).
Vous pouvez utiliser les fonctions rand()
et srand()
, à condition que votre binaire Vim inclue le patch 8.1.2342 .
Par exemple, pour générer 10 nombres aléatoires séparés par des retours à la ligne:
let seed = srand()
echo range(10)->map({-> rand(g:seed)})->join("\n")
Pour générer 10 nombres aléatoires tous inférieurs à 100:
let seed = srand()
echo range(10)->map({-> rand(g:seed) % 100})->join("\n")
Pour générer 10 chaînes alphabétiques aléatoires de 5 caractères:
let seed = srand()
echo range(10)
\ ->map({-> range(5)
\ ->map({-> (97+rand(g:seed) % 26)->nr2char()})->join('')})
\ ->join("\n")
Pour générer 10 mots aléatoires (extraits du fichier dictionnaire /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")
Pour générer 10 séquences de 5 mots aléatoires:
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")
Pour générer un UUID aléatoire version 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], '')
Pour appliquer un jeu de couleurs aléatoire:
let seed = srand()
let colorschemes = getcompletion('', 'color')
let len = colorschemes->len()
exe 'colo '..colorschemes[rand(seed) % len]
Je ne pense pas qu'il existe une fonction native pour les nombres aléatoires dans Vimscript.
Une façon d'utiliser :python
(utilisez-la dans une fonction, peut-être, avec 10000 et 60 remplacés par des paramètres):
: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
Voir ma réponse à Making a box in vim via python pour une introduction rapide sur les scripts Python dans Vim.
Puisqu'il vim.current.buffer
s'agit d'une liste de chaînes, nous pouvons lui affecter une liste de chaînes comme nous le ferions en Python. random.sample
est juste la façon la plus simple à laquelle je peux penser pour obtenir une liste d'entiers aléatoires en Python.
random.sample
ne repousse que deux arguments sur Python 2, str
c'est la fonction intégrée pour convertir les choses en chaînes. Permettez-moi de rechercher les équivalents Py3 ( str
serait le même, devra vérifier xrange
et random.sample
).
xrange
n'est pas en Python3 car elle range
est équivalente (ni ne construit réellement une liste, contrairement range
à Py2).
map
dans Py3 renvoie un itérable et non une liste, donc la dernière ligne utiliseraitlist(map(str, random.sample(range(10000), 60)))
:python
?