如何从标准输入中编辑内容?


15

我想在vim中编辑从命令行动态生成的内容,而没有文件。

例如:

$ echo This is example. | vim /dev/stdin
$ cat /etc/hosts | vim /dev/stdin

但是失败并显示以下错误:

Vim:警告:输入不是来自终端

Vim:读取输入错误,正在退出...

有可能实现吗?


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

Answers:


24

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

echo This is example. | vim -

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


7
-对于标准命令行工具,使用for标准输入是非常标准的。
马丁·图尔诺伊

6

这只是关于bash和的有趣注释readline,但是如果您将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已设置为emacsmode。如果将您的模式readline设置为vimmode,则可以使用以下命令轻松发现相关的绑定:

bind -p

和搜索edit-and-execute-commandshell-expand-line,将其分别与绑定相关联Ctrl+ x+ eMeta(Alt/Opt/Esc)+ Ctrl+ e


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

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

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

2

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

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

也可以看看:


4
请注意,这并非在所有shell中都适用。我认为它只会在工作bashzsh(不shkshdashfishcshtcsh,等)
马丁Tournoij

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

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

1
很好,因为它可以很好地推广到vimdiff <(echo foo) <(echo bar)
wchargin

@ toro2k要跟进,看起来就像在使用:next:prev重新读取流,什么也没得到。还值得一提的是,这些过程不是相互平行的(例如cat <(sleep 3; echo a) <(echo b),按顺序打印),并且在cat交错写入和读取时,vim在文件中等待“完成读取”,然后显示除外框以外的所有内容。
约翰·P

-1

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

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

除了必须删除在空缓冲区上执行此操作后保留的空第一行之外,这还行得通,并且如果Vim已经在运行,则特别方便。


1
这如何回答这个问题?
muru

它获取命令的输出并将其放入vim。
ewatt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.