我想在vim中编辑从命令行动态生成但没有文件的内容。
例如:
$ echo This is example. | vim /dev/stdin
$ cat /etc/hosts | vim /dev/stdin

,但是由于错误而失败:

Vim:警告:输入不是来自端子的
Vim:读取输入时出错,正在退出...

可以实现吗?

评论

:help stdin ...令人惊奇的是,通过询问内置文档的问题,他们能很快找到答案。

#1 楼

您必须在命令行上使用-代替文件名:

echo This is example. | vim -


以上命令将打开一个未命名的缓冲区,其中填充了从标准输入中读取的文本。

评论


对于命令行工具,在标准输入中使用-是非常标准的。

–马丁·图尔诺伊(Martin Tournoi)
15年2月12日在17:15

#2 楼

这只是关于bashreadline的有趣注释,但是如果将EDITOR环境变量设置为vim,则按Ctrl + x + e将打开vim中的当前行。此外,如果键入Meta(Alt / Opt / Esc)+ Ctrl + e,bash将在当前命令行上执行就地扩展,即:

$ echo $EDITOR # Assuming EDITOR was set


使用Meta(Alt / Opt / Esc)+ Ctrl + e将变为

$ echo vim # Assuming EDITOR was set


使用Ctrl + x + e将变为

1 echo vim # Assuming EDITOR was set
~
~
/tmp/sometmpbufferfile


请注意,退出vim时,vim缓冲区的内容在命令行上执行。

这些功能对我来说非常有用,当我想执行多行命令时在bash中,例如for循环或需要here语句的程序,并提供了一种有趣的方式来保存一些命令行历史记录以备以后使用。

因此,要回答原始问题,您也可以编写

$ This is an example


,然后按Ctrl + x + e将其加载到vim中。您也可以使用
 $ $(cat /etc/hosts)


并执行Meta(Alt / Opt / Esc)+ Ctrl + e然后Ctrl + x + e,这会将所有主机一行文件并将其加载到vim中(可能不是这些功能的最佳使用方式-但是,可以从此处讨论的几个示例中推断出这些方法的有用性)。

请注意,我假设您将readline设置为emacs模式。如果将readline设置为vim模式,则可以使用以下命令轻松找到相关的绑定:

bind -p


并搜索分别与edit-and-execute-commandshell-expand-line相关联的绑定。绑定Ctrl + x + e和Meta(Alt / Opt / Esc)+ Ctrl + e。

评论


您可以告诉bash使用vi键绑定而不是emacs。使用set -o vi将其打开。然后,您可以在正常模式下使用v映射在编辑器中编辑当前命令。

–昆西凉亭
15年2月12日在19:19

当然,使用vi编辑命令行是一个绝妙的技巧,但是使用此方法从stdin读取文本至少存在两个问题:1. shell-expand-line从扩展的文本中删除换行符;以及2.edit-and- execute-command尝试在退出vi时执行写入缓冲区的命令,无论是否保存。

–toro2k
15年2月12日在19:35

哇,太棒了我每天都在学习有关readline的新知识,看来...

–门把手
2015年2月12日在21:48

#3 楼

在bash中,我发现使用<(command)语法进行进程替换很有用,例如:

vim <(echo This is example.)
vim <(cat /etc/hosts)


另请参见:



如何非交互地编辑文件(例如在管道中)?在Vi SE上

如何将grep搜索的结果通过管道传输到unix SE上的新vi文件中


评论


请注意,这并非在所有shell中都适用。我认为它仅适用于bash和zsh(不适用于sh,ksh,破折号,鱼,csh,tcsh等)

–马丁·图尔诺伊(Martin Tournoij)
15年2月12日在17:17

@Carpetsmoker我认为应该在ksh88及更高版本中工作,但是是的,进程替换不是POSIX。

–muru
2015年2月12日在18:41



并注意不要欺骗自己!当您以这种方式启动Vim时,它将为/ proc / PID / fd / FD之类的文件打开一个缓冲区。如果您编写缓冲区并退出,Vim不会抱怨,但是您写入的文件将被操作系统删除。使用-作为文件名,打开的缓冲区没有与之关联的文件,因此,如果您尝试退出而未保存Vim(只要您不使用bang命令或类似命令),就会警告您。

–toro2k
2015年2月12日在19:48



这很好,因为它可以很好地概括为vimdiff <(echo foo)<(echo bar)。

– wchargin
15年2月20日在15:42

@ toro2k要跟进,好像使用:next和:prev重新读取流并什么也没有。还值得一提的是,这些过程不是彼此并行的-例如cat <(sleep 3; echo a)<(echo b)按顺序打印-当cat交错写入和读取时,vim在显示文件(除外框之前)等待文件“完成读取”。

– John P
17年12月31日在13:57

#4 楼

如果不需要使用到新Vim的管道,则可以使用Vim的功能将命令输出拉入当前缓冲区,同时具有不支持文件的缓冲区(例如:new或编辑不存在的文件) )

:read!cat /etc/hosts在命令模式下会将输出放置到当前缓冲区当前光标位置下方的当前缓冲区中。

除了必须删除在此位置保留的空第一行在空缓冲区上完成此操作非常有效,如果Vim已在运行,则特别方便。

评论


这如何回答这个问题?

–大师
15年2月19日在8:39

它获取命令的输出并将其放入vim。

–瓦特
15年2月19日在8:43