是否可以在VIM中重用ex命令的范围?
例如,我可以使用以下命令将当前文件中的第4到第10行写入(复制)到新文件中:
:4,10w foo/bar.txt
但我真正想做的是将线条移动到新文件。我可以这样做:
:4,10w foo/bar.txt
:4,10d
但是两次输入4,10都有点烦人。
所以我有两个问题:
答案 0 :(得分:5)
我通常用猫来做这件事:
:4,10!cat > foo/bar.txt
这是有效的,因为你通过cat管道线并用结果输出替换它们,这没什么。当然,您可以通过执行>>追加到现有文件的末尾。而不是>。
答案 1 :(得分:4)
我不知道(1)的答案,但回答(2),有许多不同的方法,不需要手动重新选择线。在可视模式下,这将起作用:
4GV10G
:w foo/bar.txt
gvd
因为gv重新选择了之前的选择,这几乎是你想要的,而不使用ex范围。
但你可以把问题放在首位,然后尝试:
:4,10d
:sp foo/bar.txt
pZZ
剪切,然后粘贴到新文件中,然后关闭它。
答案 2 :(得分:3)
除了使用Vim历史记录(: Cursor Up ,q:
)并删除上一个命令以便只保留范围之外,没有办法重复使用最后一个范围,没有魔法变量。
如果我经常使用此移动线组合,我会为它编写一个自定义命令:
command! -bang -range -nargs=1 -complete=file MoveWrite <line1>,<line2>write<bang> <args> | <line1>,<line2>delete _
您只需指定一次范围并保存输入。
你也可以为其他组合写这样的东西。主要挑战是指定所有命令属性(爆炸,范围,完成),以及稍后记住自定义命令名称。
答案 3 :(得分:2)
这是一个实现此目的的命令行映射。我将它绑定到CTRL-G CTRL-U,因为它执行与CTRL-U类似的操作。 (但你当然可以改变它!)
" c_CTRL-G_CTRL-U Remove all characters between the cursor position and
" the closest previous |:range| given to a command. When
" directly after a range, remove it.
" Useful to repeat a recalled command line with the same
" range, but a different command.
let s:singleRangeExpr = '\%(\d\+\|[.$%]\|''\S\|\\[/?&]\|/[^/]*/\|?[^?]*?\)\%([+-]\d*\)\?'
let s:rangeExpr = s:singleRangeExpr.'\%([,;]'.s:singleRangeExpr.'\)\?'
let s:upToRangeExpr = '^\%(.*\\\@<!|\)\?\s*' . s:rangeExpr . '\ze\s*\h'
" Note: I didn't take over the handling of command prefixes (:verbose, :silent,
" etc.) to avoid making this overly complex.
function! s:RemoveAllButRange()
let l:cmdlineBeforeCursor = strpart(getcmdline(), 0, getcmdpos() - 1)
let l:cmdlineAfterCursor = strpart(getcmdline(), getcmdpos() - 1)
let l:upToRange = matchstr(l:cmdlineBeforeCursor, s:upToRangeExpr)
if empty(l:upToRange)
return getcmdline()
else
call setcmdpos(strlen(l:upToRange) + 1)
return l:upToRange . l:cmdlineAfterCursor
endif
endfunction
cnoremap <C-g><C-u> <C-\>e(<SID>RemoveAllButRange())<CR>
答案 4 :(得分:1)
通常,我要做的是从一个文件中删除行,切换到另一个文件,然后粘贴。
另外,我通常使用标记。我没有输入实际数字,而是点击mb
标记开始行,然后转到结束行并点击d'b
以删除标记为b
的行。但您可以使用mb
标记开始行,使用me
标记结束行,然后运行ex命令:
:'b,'e w somefile.txt<Enter>
当然,您可以使用a
到z
中的任何字母作为标记;我通常使用b
和e
,但您可以使用自己喜欢的内容。
我如何移动线条:
m'b
<navigate to end line>
d'b
:n somefile.txt<Enter>
p
Ctrl+^
Ctrl + ^从当前打开的文件切换到上一个打开的文件。 (如果您愿意,也可以打开一个窗格并切换窗格。窗格不能在普通的vi中工作,但在vim中工作。)
以上假设您已设置autowrite
选项。使用autowrite
,:n
命令和Ctrl + ^都只是编写当前文件然后切换文件,而不是抱怨文件已更改而不保存。您也可以执行上述操作,只需在使用:n
或Ctrl + ^。
顺便说一下,我使用Ctrl + ^,以至于我把它映射到K
。打字比较容易,但很久以前我养成了这种习惯,以前我常常不得不使用一个无法输入Ctrl + ^的哑终端。
顺便说一下,当你删除行时,它们会进入“未命名的缓冲区”。在vim中,切换文件时会保留未命名的缓冲区。在原始vi中,清除未命名的缓冲区。所以上面的内容不适用于旧的vi。您可以通过删除命名缓冲区,然后从命名缓冲区粘贴来使其工作;适用于任何版本的vi。
m'b
<navigate to end line>
"ad'b
:n somefile.txt<Enter>
"ap
Ctrl+^
上面删除了名为a
的缓冲区,然后从a
粘贴到另一个文件中。这当然适用于vim;只是你不需要它。
答案 5 :(得分:1)
您也可以这样做,将匿名注册的内容写入file2.txt
:4,10d | :call writefile(split(@@, "\n", 1), 'file2.txt')
答案 6 :(得分:0)
您可以先删除,然后打开新标签并粘贴内容 - 所以:4,10d
,然后是:tabe foo/bar.txt
,然后是p
...听起来会更好吗?
答案 7 :(得分:0)
在撰写本文时,在Vim 8和NVIM 0.3.7中,您实际上可以编辑命令列表,然后按Enter键来执行。
:4,10w foo/bar.txt
q:
q:
是输入交互式ex命令
打开交互式命令列表后,您可以对其进行编辑并按Enter键来执行。
尽管我爱moopet's answer,但效率很高。