3

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

我已经知道我可以将当​​前缓冲区中的行作为标准输入(请参阅参考资料:help :w_c)。但是我不想修改当前的缓冲区,也不想做一个新的缓冲区。

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

可以做到吗?

4

3 回答 3

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
于 2013-08-25T18:55:43.417 回答
2

对于后代,这是我在四处乱窜时想出的另一个答案。

@Kent 的答案看起来像是将标准输入传递给命令的规范 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。那好吧。

于 2013-08-25T20:34:01.083 回答
2

您还可以将列表传递给 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 月,如果这对您很重要,尾随空行将被截断)

于 2018-01-06T18:48:57.453 回答