我可以将字符串作为stdin传递给来自vim的系统调用吗?

时间:2013-08-25 18:43:29

标签: stdin vim

我想从vim(:help :!)运行系统命令,我想将字符串变量的内容作为该命令的stdin传递。

我已经知道我可以pass lines from the current buffer as stdin(见:help :w_c)。但我不想修改当前的缓冲区,我也不想创建新的缓冲区。

我知道我可以将字符串写入临时文件,然后将该文件作为输入进行管道并删除它。现在,这是我知道的应用程序的最佳解决方案。但是,首先避免创建文件会更清晰。

可以吗?

3 个答案:

答案 0 :(得分:6)

所以基本上,你有一个变量,比方说,一个字符串,你想把这个变量传递给一个外部命令,并在一个变量而不是缓冲区中获得返回值。

如果上述情况正确,您可以这样做,请参阅以下示例:

let s="vim is good"
let r=system("sed 's/good/the best/'",s)
echo r
"display vim is the best
echo s
"display vim is good

答案 1 :(得分:2)

对于后人来说,这是我在黑客攻击时想到的另一个答案。

@ Kent的答案看起来像是将stdin传递给命令的规范vim方式。它使您免于管理临时文件。但是,如果(无论出于什么原因)你想要避免创建文件的开销呢?这是一种方法。

基本形式是

echo your_string | your_command

当然,正确获取细节非常容易出错,因此我建议将其包装在一个函数中:

function! RunCommandWithStdin(cmd, stdin_lines)
  let l:stdin = shellescape(join(a:stdin_lines, "\\n"), 1)
  execute '!echo -e' l:stdin '|' a:cmd
endfunction

使用patch

快速检查健全状况
:!echo foo > bar
:!cat bar
foo
:call RunCommandWithStdin('patch bar', ['@@ -1 +1 @@', '-foo', '+~!@#$%^&*()'])
:!cat bar
~!@#$%^&*()

请注意,这似乎正确处理特殊字符。

缺点是它使用echo,所以它可能仅限于* nix-alikes。哦,好吧。

答案 2 :(得分:1)

您还可以将列表传递给system(),为您的命令提供多行STDIN:

所以:

let s=["perl is good", "perl is complicated"]
let r=system("sed 's/perl/vim/'", s)
echo r
"vim is good
"vim is complicated

另请注意,在这种情况下,您可以使用systemlist()将结果作为列表(截至2018年1月,如果这对您很重要,则会删除尾随空行)