假设我想编辑一个新的 libvirt XML 文件:
virsh dumpxml machine1 > machine2.xml
然后我用打开文件vim
,
vim machine2.xml
然后我想更改 UUID。现在这样做,我用
:r ! uuidgen
但新的 UUID 会插入到当前行下:
<uuid>6r123ttz-6t01-356t-1y7h-g7oe196c8u3m</uuid>
e67baf90-751b-4aea-a14b-aca1b881542b
如何插入uuidgen
命令的输出进入当前行,所以如果我有
<uuid></uuid>
(光标在 之间><
),然后,通过执行uuidgen
我得到
<uuid>e67baf90-751b-4aea-a14b-aca1b881542b</uuid>
问题是:是否可以使用:r
vim命令而不添加新行?
答案1
:read
是一个前命令;不幸的是这些总是有效完整的线路。您要么必须先拆分,然后再加入前面和后面的行,要么使用不同的命令来解决这个问题。
这:help i_CTRL-R
命令可以插入任意寄存器内容。有一个特别的表达式寄存器(:help quote=
) 执行任何 Vimscript 表达式并使用其结果。最后,system()
函数执行外部命令并返回其输出。
因此(在插入模式下)<C-R>=system('uuidgen')<CR>
将在当前位置插入命令的输出。不幸的是,输出有一个尾随换行符,并且该换行符被保留,因此</uuid>
移动到下一行。为了避免这种情况,您可以通过system('uuidgen')[0:-2]
或substitute(system('uuidgen'), '\n$', '', '')
作为表达式截断输出。
对于重复插入,表达历史可用于调用最后一个表达式(按<Up>
);为了更加舒适,您可以为整个事物定义一个映射。
答案2
我玩了一下,这并不完全符合你的要求,因为 :r 总是会输入换行符。但它应该做你想要的结果。
:.!UUID=`uuidgen` ; echo "<uuid>$UUID</uuid>"
它将标准输出放在当前行(而不是光标处) - 智能是通过正在调用的命令完成的。
答案3
fu! SetBang(v) range
if a:v == 1
normal gv
endif
let l:t = &shellredir
let &shellredir = ">%s\ 2>/dev/tty"
let @" = join(systemlist(input("\"!"))," ")
let &shellredir = l:t
endf
nnoremap "! :cal SetBang(0)<cr>
xnoremap "! :cal SetBang(1)<cr>
每次按下"!
,都会提示用户输入命令,并且“未命名”"
寄存器将被填充。然后,您可以照常插入它,在P
正常或可视模式下,在Ctrl-R"
插入模式下等。
例如,有文本(插入符号由 表示|
):
<uuid>|</uuid>
并按"!uuidgen<Enter>P
将在插入符号处插入新的 uuid。
您当然可以使用其他绑定来代替"!
.
答案4
您还可以直接编辑 XML,甚至无需使用vim
.
例如,<uuid></uuid>
作为文件的一部分给出,您可以插入或更新该值:
echo '<uuid></uuid>' |
xmlstarlet edit --update '//uuid' -v "$(uuidgen)"
输出
<?xml version="1.0"?>
<uuid>79cc09da-a256-46d5-9974-9073cf9d7a9a</uuid>
这可以让您对虚拟机定义进行模板化并以编程方式对其进行自定义。