我想生成一个或几个用换行符分隔的随机数。

如何做到这一点?

评论

纯Vim吗?或者说,使用:python?

纯vim是首选,但如果不是内置的,则任何易于记忆的方法都可以。

#1 楼

从Vim 8.1.2342开始,您可以使用rand()srand()函数。
这里是一个示例:
let g:seed = srand()
echo rand(g:seed) % 100   " to echo a random number between 0-99

对于较旧的Vims,您必须回过头来调用一些外部命令(如果启用了Vim,则使用Python,Perl,Tcl,MzScheme,Ruby,Lua语言接口)。

UNIX Shell(/bin/sh
调用:
strings -n 1 < /dev/urandom | tr -d '[:space:]' | head -c15

system()是个好方法。您可以通过用tr替换grep来获得数字:
strings -n 1 < /dev/urandom | grep -o '[[:digit:]]' | head -c15

可以在Vim中这样使用:
:echo system("strings -n 1 < /dev/urandom | grep -o '[[:digit:]]'  | head -c15")

数字15是您想要的数字数量(调整相应地)。这应该在Linux,BSD,OSX和其他UNIX系统上起作用。它不能在MS Windows上运行。
也请参阅我的博客文章“从命令行生成密码”(那里有很多错误的解决方案)。
Ruby
Ruby是可能是下一个最佳选择,因为Ruby脚本似乎比Python脚本更常见。获得随机数很容易:
:ruby puts Random.rand(10)

或获得15个数字:
:ruby 15.times { puts Random.rand(10) }

Python
您可以使用random模块;以获得一个数字:
:py import random; print(random.randint(0, 9))

或15个数字:
:py import random
:py for i in range(0, 15): print(random.randint(0, 9))

这对Python 2和3均适用。
Windows PowerShell
可以使用Get-Random
:echo system('Get-Random')

Windows cmd.exe

Windows 7和更高版本应随PowerShell一起提供,但如果要最大化
兼容性可以使用cmd.exe。它有一个特殊的变量%RANDOM%
:echo system('@echo %RANDOM%')

注意:这不是很随机!
,它使用时间(!)需要使用Ruby或Python绑定才能使用Ruby或
Python解决方案;您还可以创建一个单独的脚本,并使用
system("python -c '...'")进行调用(显然,这确实需要安装ruby / python,


评论


代替tr -d'[:space:]',也许是grep过滤器使用tr -cd'[:digit:]'吗?

–muru
2015年2月14日在23:33



@muru我不确定在OSX上是否可以使用,这就是为什么我不使用它的原因...您还以这种方式用换行符分隔了数字,就像OP要求的...。

–马丁·图尔诺伊(Martin Tournoij)
2015年2月14日在23:35



如果真是这样... GNU击败了BSD。 :P

–muru
2015年2月14日在23:36

也可以使用shell(系统)输入随机数,即:r! hexdump -n $(((3 * 4))-e'“%d”'/ dev / urandom,将生成3个随机有符号整数。

– HAL 9001
15年2月15日在7:13

@kenorb这将正确使用shell输入3个带符号的随机整数::r! hexdump -n $(((3 * 4))-e'“ \%d \ n”'/ dev / urandom

– HAL 9001
2015年2月16日在17:49



#2 楼

这是一个纯vimscript解决方案。我没有创建它,它是由Charles E. Campbell开发的。您可以在此处找到带有他的代码的Github存储库。该算法使用Vim启动时生成的3个种子,并根据应用于种子的计算和置换生成伪随机数:

" 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


变量范围被声明为全局变量,因为它们由生成器函数使用,但可能仅限于脚本(s:

这是生成器函数:

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



回购包含以下功能:


“随机” “种子的初始化;
从文本文件中读取用户定义的种子的方法;
伪随机生成器
多个随机函数:


在一定范围内生成随机数的函数
骰子滚动函数
随机交换一系列连续整数的函数




这是我编写的用于测试生成器的快速测试:我生成了0000000、9和c之间的1000000个数字忽略每个数字的出现次数,这里是结果:

0 : 100409
1 : 99435
2 : 100433
3 : 99578
4 : 100484
5 : 99948
6 : 100394
7 : 99649
8 : 99803
9 : 99867


如您所见,世代似乎分布良好。我知道这在很大程度上不足以测试随机生成器,因此如果有空闲时间,我将尝试进行一些额外的分析。

#3 楼

这是一种在vim-randomtag插件中找到的方法,该方法基于以下信息:...当前时间微秒,仅在需要一些数字,对随机性质量不太关心或有安全方面的关注时可用。 br />
function! s:randnum(max) abort
  return str2nr(matchstr(reltimestr(reltime()), '\v\.@<=\d+')[1:]) % a:max
endfunction


#4 楼

您可以使用rand()srand()函数,前提是您的Vim二进制文件包含补丁8.1.2342。


例如,生成10个由换行符分隔的随机数:

let seed = srand()
echo range(10)->map({-> rand(g:seed)})->join("\n")


要生成10个均小于100的随机数:

let seed = srand()
echo range(10)->map({-> rand(g:seed) % 100})->join("\n")


要生成10个由5个字符组成的随机字母字符串:

let seed = srand()
echo range(10)
   \ ->map({-> range(5)
   \           ->map({-> (97+rand(g:seed) % 26)->nr2char()})->join('')})
   \ ->join("\n")


要生成10个随机词(取自词典文件/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")


要生成10个5个随机词的序列:

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")


要生成随机UUID版本4:

" Based on this answer: https://stackoverflow.com/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], '')


要申请随机配色方案:

let seed = srand()
let colorschemes = getcompletion('', 'color')
let len = colorschemes->len()
exe 'colo '..colorschemes[rand(seed) % len]


#5 楼

Vim不提供本机随机生成器,但是,如果您使用Python编译了vim,则以下方法将在行尾添加一个随机数字:

:py import vim, random; vim.current.line += str(random.randint(0, 9))


注意:要检查您的vim是否支持Python,请尝试::echo has('python')(如果是,则为1)。

您还可以使用提供$RANDOM变量(与bash / ksh / zsh一起使用)的shell,该变量返回伪随机( 0-32767),例如:

:r! echo $RANDOM


或:

:put =system('echo $RANDOM')


或:

:r! od -An -td -N1 /dev/urandom


在Windows上,您必须安装Cygwin / MSYS / SUA,或者按照Carpetsmoker的建议使用%RANDOM%变量。

如果您没有对于shell和Python的访问,作为解决方法,请使用当前时间戳的最后几位数字,例如:

:put =reltimestr(reltime())[-2:]


注意:如果您经常使用它,编写一个简单的函数return reltimestr(reltime())[-4:]


注意:以上方法仅返回一个伪随机整数,不应将其用于ge请对加密密钥进行加密。



要添加更多随机数,请按@:再次重复该命令。或以数字作为前缀(例如10 @ :),以添加更多由新行分隔的随机数。


相关:



VIM在stackoverflow的缓冲区中生成随机数

在stackoverflow的bash中生成随机数


评论


它也适用于zsh,但不适用于sh,破折号,鱼,csh或tcsh ...您可以使用:r! bash -c'echo $ RANDOM'...

–马丁·图尔诺伊(Martin Tournoij)
2015年2月15日在23:24



“从当前时间戳返回最后几位数字”->这不是随机的。即使是出于非加密目的,使用时间来获取伪随机数几乎总是一个坏主意。如果时间戳的分辨率以秒为单位,并且每秒创建两次“ file。$ random”,该怎么办?糟糕! ...另外,您永远都不知道何时有人要使用您的GetRandom()函数对prng有什么影响,因此,如果可能的话,最好从一开始就将其正确设置(并且几乎总是可以在这里实现!)

–马丁·图尔诺伊(Martin Tournoij)
2015年2月16日在10:06



我不知道$ RANDOM的质量如何,但是如果这不是一个较差的PRNG,那么这不是使用更差的PRNG的理由:-)相反,请升级到更好的PRNG!据我所知,/ dev / urandom在bash普遍可用的所有平台上都可用,因此我看不出不使用它的理由。

–马丁·图尔诺伊(Martin Tournoij)
2015年2月16日在10:59



我不知道$ RANDOM。似乎是一个非常不错的小工具,即使它可能是“穷人RNG”(如@Carpetsmoker指出的那样),也绝对符合@kenorb(提出问题的人)“容易记忆”的要求。

–Dalker
16-10-7在14:46

#6 楼

我认为Vimscript中没有随机数的本机函数。

使用:python的方法(在函数中使用它,也许用10000和60替换了参数):

: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


请参阅我对通过python在vim中创建框的回答,以快速了解Vim中的Python脚本。

由于vim.current.buffer是字符串列表,因此我们可以像在Python中那样为它分配一个字符串列表。 random.sample只是我想到的在Python中获取随机整数列表的最简单方法。

评论


@Carpetsmoker random.sample在Python 2上仅提供两个参数,str是将内容转换为字符串的内置函数。让我查找Py3等效项(str相同,必须检查xrange和random.sample)。

–muru
2015年2月14日在23:47

@Carpetsmoker aargh,错字。 60之后的括号应该在10000之后。xrange在Python3中不存在,因为range是等效的(与Py2中的range不同,它们实际上都不构造列表)。

–muru
15年2月14日在23:55

@Carpetsmoker最后的区别是Py3中的map返回一个可迭代的列表而不是列表,因此最后一行将使用list(map(str,random.sample(range(10000),60)))

–muru
2015年2月14日在23:58

好的,我可以自由地通过一些(较小的)更改来编辑您的文章,以使其与Python 2和3兼容...

–马丁·图尔诺伊(Martin Tournoij)
2015年2月15日下午0:51

#7 楼

Vim v8.1.2342添加了randsrand函数。
我更喜欢这种方式在当前缓冲区中生成0-100范围内的20个随机数:
:put =rand()%100
20@: