vim 脚本在标准输入中留下字符

vim script leaves characters in stdin

我正在尝试使用 vim 和 -s 选项来运行一个脚本来替换文件中的某些行,如下所示 (text.txt):

test1
ab
ac
ae
test2
sd

脚本文件是这样的(脚本):

:silent %s/test1\zs\_.\+\zetest2/\=substitute(submatch(0), '\n\(\w\)', '\n#', 'g')/g
:wq

它注释掉了 test1 和 test2 之间的行。这就是我想要的。我不想要的是提示前后的输出。我运行它并得到:

user@hostname: ~/vimtest$ vim -s script text.txt 
^[[?1;2cuser@hostname: ~/vimtest$ 1;2c

所以这个 ^[[?1;2c 已经是个坏消息了,但是 1;2c 在输入中,就好像我已经输入了一样。如果我按回车键,它会给我一个 bash 错误。所以每次使用脚本时我都必须删除这些符号。有什么想法吗?

:%s/test1\zs\_.\+\ze\ntest2/\=substitute(submatch(0), '\n', '\n#', 'g')/g
:wq

这是在这里测试的,它按要求的方式更改了输入文件。

根据您的命令完成的一些更改:

  • \ze
  • 之后添加\n
  • 在substitute()函数中我们可以只处理\n,我们不需要捕获\n
  • 后面的词

我注意到你用 bash 标记了问题,所以我认为 shell 的解决方案也应该被接受。

awk '/test1/{p=1;print;next}/test2/{p=0;print;next}{[=10=]=(p?"#":"")[=10=]}7' file

这个 awk oneliner 应该可以为您做到这一点。 vim 很强大的编辑器,我喜欢vim。但如果你想做一些自动转换,我更喜欢脚本或适当的文本处理工具。在 linux 盒子上,您总能找到一个。更容易测试和调试。

使用您的输入进行测试:

kent$  cat f
test1
ab
ac
ae
test2
sd

kent$  awk '/test1/{p=1;print;next}/test2/{p=0;print;next}{[=11=]=(p?"#":"")[=11=]}7' f
test1
#ab
#ac
#ae
test2
sd

如果您想将文本保存回您的文件,您可以:

awk '...' file > tmp.file && mv tmp.file file

似乎 vim(或某些 vim 启动脚本)正在尝试找出您使用的终端类型。 ^[[?1;2c,最后几个字符留在输入缓冲区中,几乎可以肯定是终端仿真器对 DA(设备属性)查询的响应的一部分。您可以通过输入 bash:

自己查看
printf '3[c'

或者,要查看完整的 return,稍等片刻:

printf '3[c'; sleep 0.1; echo

响应 3[?1;2c 表示 "I'm a VT100 with Advanced Video Option.",这是 xterm 和许多其他控制台程序的响应。 (Linux 控制台本身响应 3[?6c,这意味着 "I'm a VT102.")

控制台输入缓冲区中只剩下1;2c的原因,顺便说一下,是初始转义码3[?在读取时被忽略了。 readline 库会忽略它而不回显它,而正常的控制台输入会回显它然后忽略它;这就是上面两个 shell 命令不同的原因。

我的 vim 安装无法重现这个问题,所以我什至不知道从哪里开始寻找。但是您可以尝试查看禁用所有启动文件是否有帮助:

vim -u NONE -s script text.txt

如果有帮助,请开始一个一个地禁用已安装的扩展,直到找到导致问题的那个。