如何将当前缓冲区或行作为stdin发送到vim中的system()?

时间:2014-02-03 14:54:48

标签: shell stdout stdin vim

有3个密切相关的vim命令可以让你调用外部程序:

  1. :[range]!{filter-cmd} {arg}(前命令,:help :range!

  2. :[range]write !{cmd}(前命令,:help :w_c

  3. system({expr}, {arg})(vimscript函数,:help system()

  4. (我包括!:!cmd作为1的一部分。)

    从我的观点来看,有三个重要的区别:

    1. [range]被发送到stdin,stdout替换[range]
    2. [range]被发送到stdin,stdout被忽略
    3. stdout是system()的返回值,因此stdout可以保存为变量:let @a = system(..)
    4. 真的没有办法将当前缓冲区或当前行作为stdin发送到外部命令并且无限制地访问stdout吗?

      如果你想编写一个复杂的移动命令,需要解析行/缓冲区(解析最好不要用vimscript编写),这似乎非常令人惊讶。

      (尝试通过{arg}发送内容会因为以下几个原因而疯狂:1。字符长度限制,2。您必须在vimscript中编写shell转义函数*)

      这是我能找到的唯一其他相关问题。它将一个字符串变量作为shell参数发送到(unix)'echo',然后将其作为stdin发送到您的程序:Can I pass a string as stdin to a system call from vim?

      *如果vim函数shellescape()能够达到你想要的效果,那就太棒了,但是在Windows上,保护来自cmd.exeCommandLineToArgvW的输入甚至不具备远程可靠性。实际上,在Windows上,vim通过cmd.exe 两次发送任何单个shell字符串

1 个答案:

答案 0 :(得分:4)

好的,我错误地提到了一个非常重要的细节:system({expr},{input})的第二个参数不被视为shell输入,它作为stdin发送。所以你会做类似的事情:

:let stdin = join(getline(1,'$'), "\n")
:let a = system('C:/main.exe',stdin)

几乎system(..)的所有示例都使用并警告shell转义,但这是针对{expr}参数的(如果{expr}不是动态字符串,则转义是一个小得多的问题)。