我的最终目标是在句子分隔符上拆分文本。然而,它不应该被分成句子,而是在块中。1000 行,加上当前句子的其余部分。但在下面的实验中,为了简单起见,我只使用了 2 行。
考虑 VIM 缓冲区中的以下文本:
line 1. line 1. line 1.
line 2. line 2. line 2.
line 3. line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.
执行后:
:2 | exec 'normal! )hvgg' | exec "'<,'>w /tmp/part1.txt" | exec 'normal! gvd'
结果符合预期。缓冲区包含:
line 2. line 2.
line 3. line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.
但是在下一次运行之后
:2 | exec 'normal! )hvgg' | exec "'<,'>w /tmp/part2.txt" | exec 'normal! gvd'
缓冲区包含:
line 2.
line 3. line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.
这里发生了什么?为什么它不移动到第二行line 3. line 3. line 3.
?
但我希望以下文本保留在缓冲区中
line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.
问题的根源在于
gv
最后。这是不必要的,因为视觉选择从命令的前一部分持续存在。更糟糕的是,这并不是无害的,因为当您gv
已经处于可视模式时,当前和以前的可视区域会交换。意味着之前的选择被重新选择了!即使先前的选择被删除,选择也会应用于同一区域……或者至少是它的剩余部分。在这种情况下,这将是剩余
line 2.
句子中的第一个。为了演示,请注意输入两次时会发生什么:
2G)hvgggvd
. 这正是命令行上发生的事情,减去写入磁盘,但使用 100% 正常模式命令。所以无论如何我们只需要失去
gv
并且这将起作用:除此之外,此命令中还有很多可以清理的噪音。
exec
不需要两个s 和随附的引号:更新:针对您的其中一个评论...
是一种逐行操作,从最后选择的可视区域的第一行到同一区域的最后一行进行选择。要获得字符明智的范围,您需要像这样使用 back-tics:
但是,这不适用于
:w
......它只是一个逐行操作。我要指出的是,这超出了您的问题的范围,该问题询问为什么要删除特定的文本......所以您可能想针对按字符写入文件提出一个单独的问题。
更新 2:这是解决您的问题的完全不同的方法......
使用以下命令创建宏
:let @a = 0
.@q
这将按照您描述的方式运行:句子及其上方的所有内容都将写入一个名为的文件
/tmp/part1.txt
,并且保存的文本将被删除。现在移动到任何其他句子并@q
再次执行,这一次会发生同样的事情,但它会写入/tmp/part2.txt
. 每次运行宏时,文件名都会自动递增。您可以使用 再次重置索引:let @a = 0
。与之前的更新一样,这并没有解决所提出的实际问题,但因为我很好,我提供了一些额外的帮助。(而且 OP 仍然不会接受我的回答。)
我终于找到了公认的解决方案。感谢@B 层的合作(例如,提到该
w
命令仅将整行写入文件)。我赞成你的回答。之后,如果最后一个块短于 1000 行,则按重复命令,
@:
您将收到错误消息。只需手动保存其余部分。经过 5 次处决后,我得到了预期:
对于那些想要使用它的人,我将简要解释关键步骤:
:1000
移动到第 1000 行(块至少应为 1000 行)
移动到下一个句子的开头并返回一个字符,这样下一个句子的第一个字符就不会被删除。要正确处理分布在多行的句子,
whichwrap=h,l
应该设置,据我所知,这不是默认设置。选择从当前光标位置到开头的所有内容并将其删除。删除的内容将保存在寄存器中。将寄存器内容(块)写入文件
我假设不会超过 99 个块。如果需要更多,请根据需要调整与填充相关的部分。