如何在 Vim 中生成 GUID?

6

Vim没有内置的GUID生成器。

对于我正在进行的项目,我可以依靠PowerShell可用性来生成GUID字符串:

[guid]::NewGuid().ToString()

我在替换操作中调用此函数,如下所示:

...

%s/foo/\=system('[guid]::NewGuid().ToString()')[:2]/

虽然这种方法可以使用,但是每个替换都会弹出一个窗口,并且速度相对较慢。

我真正想要的是一种在Vim内快速且可移植生成GUID的方法。


在你的例子中,你将GUID截断为前3个字符([:2]);这会丢失唯一性属性,并将GUID转换为基本(有些随机)数字。你确定需要完整的GUID,还是只需要一个N位的随机数? - Ingo Karkat
抱歉,应该是 [:-2] - 只需将末尾的垃圾修剪掉。 - Rik Hemsley
正如此链接所述,您需要设置 set shellquote=\"set shellxquote= 才能使 system() 在 powershell 中正常工作。 - user1129682
7个回答

13

如果您可以依赖于Vim可用的Python脚本支持

:pyx import uuid
:%s/foo/\=pyxeval('str(uuid.uuid4())')/

如果你的Vim和Python非常老旧,请使用 :pypyeval() 代替 :pyxpyxeval()


很遗憾,我使用的是Windows系统,没有Ruby或Python可用 - 在Vim内部完成是理想的选择。 - Rik Hemsley
1
今天我尝试了这个解决方案,但发现 pyeval 不可用,所以最终做法是::py vim.command("s/nguid/" + str(uuid.uuid4()) + "/g")...然后使用 vim 宏重复执行。虽然不是理想的方法,但已经足够好了,感谢您提供的起点。 - Rik Hemsley
这非常有用。我将其与 :nnoremap <Leader>s :%s/\<<C-r><C-w>\>/\=pyeval('str(uuid.uuid4()')/ 和宏结合使用,轻松解决了我的特定问题。所以我真正需要做的就是 \s,它用 uuidv4 替换了我的搜索字符串。 - matchew

3

如果您不想或无法使用Vim语言包装(例如Python或Perl),则必须为Win32 UuidCreate()函数编写DLL包装器,并通过libcall()从Vim调用该函数。 (帮助文档指出,您无法直接调用Windows系统DLL,因为调用约定不匹配。)

这个包装器可能很简单且容易编写,但仍然需要编译DLL并在每个系统上安装。


2
替换
'[guid]::NewGuid().ToString()'

使用

'powershell.exe -command "[guid]::NewGuid().ToString()"'

那能帮到您吗?

这就是我已经在做的事情 - shell 已经设置为 PowerShell,但还是谢谢。 - Rik Hemsley

2
我猜你只是想用随机十六进制替换foo。如果是这样,你可以像这样做:

M$ Windows:

%s/foo/\=printf("%04X",libcallnr("msvcrt.dll","rand",localtime()))[:2]/

对于Unix系统:

%s/foo/\=printf("%04X",libcallnr("libc.so.6","rand",localtime()))[:2]/

这将比任何其他shell命令都要快得多。


使用libcall()的好例子。不幸的是,GUID != 随机数;后者不能保证唯一性。 - Ingo Karkat
@IngoKarkat 您是正确的,GUID 不是随机数。但考虑到使用情况:它只使用 GUID 的前三个十六进制数字。以及 GUID 的实现方式。所以我只是“猜测”它可以被一个随机数生成器替换。 :) - Yi Zhao
很好的发现;我没有完全意识到GUID输出被截断了。这使得你的解决方案成为一个很好的选择;+1 - Ingo Karkat

2

假设你的路径中已经有了python,下面是一些插入或追加UUID到光标位置的映射。它应该是与平台无关的。

" Insert GUID
nnoremap <silent><leader>ig "=system('python -c "import uuid; print(uuid.uuid4(), end=\"\");"')<CR>P

" Append GUID
nnoremap <silent><leader>ag "=system('python -c "import uuid; print(uuid.uuid4(), end=\"\");"')<CR>p

工作原理:

  • python -c "import uuid; print(uuid.uuid4(), end=\"\");"' - 这是一个使用 pythonuuid 模块打印 UUID 到 STDOUT 的 shell 一行命令,不带换行符。
  • "= - " 告诉 vim 将下一个值分配给指定的寄存器,本例中为表达式寄存器:=
  • system(...) - 这个命令将外壳分离并重定向输出以供分配到寄存器中使用
  • <CR>P<CR>p - 在光标处评估并粘贴寄存器(分别为插入、追加)

1
我到这里来是因为问题标题询问如何创建UUID,然而问题文本实际上想要用新创建的UUID替换现有的文本块。 Marius Gedminas' Answer 让我走得很远,如果其他人需要创建和插入UUID,这就是方法:
function! Guid()
python << EOF
import uuid, vim
vim.command("normal i" + str(uuid.uuid4()) )
EOF
endfunction

如果您想将其映射到<alt+G>: map <m-g> :call Guid() <cr> (如果您的Gvim在调用Python时崩溃,请阅读此文)

1
在Windows上,system()命令会弹出一个命令窗口(通常在后台)。避免这种情况的一种方法是使用编译到Vim中的语言绑定,例如Python:
:python import uuid, vim; vim.command("let g:uuid = '" + str(uuid.uuid1()) + "'

这种方法既更快,又避免了弹出窗口,但需要安装Python和支持Python的Vim;如果您因某种原因更喜欢其他语言,可以考虑使用类似的Perl或Ruby实现。不幸的是,目前还没有PowerShell语言绑定。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接