有时我需要编写文本,然后将该文本通过管道传输到另一个命令中。我通常的工作流程是这样的:
vim
# I edit and save my file as file.txt
cat file.txt | pandoc -o file.pdf # pandoc is an example
rm file.txt
我发现这很麻烦,并且寻求学习 bash 脚本,我想通过编写一个命令来打开编辑器,并在编辑器关闭时将编辑器的输出通过管道传输到标准输出,从而使过程变得更加简单。然后我就可以运行该命令了quickedit | pandoc -o file.pdf
。
我不确定这会如何运作。我已经编写了一个函数,通过遵循上面的确切工作流程并添加一些附加内容来自动执行此操作。它生成一个随机字符串作为文件名,并在调用函数时将其传递给 vim。当用户通过保存文件退出vim时,该函数将文件打印到控制台,然后删除该文件。
function quickedit {
filename="$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32)"
vim $filename
cat $filename
rm $filename
}
# The problem:
# => Vim: Warning: Output is not to a terminal
我很快遇到的问题是,当我做类似quickedit | command
vim 之类的事情时,它本身不能用作编辑器,因为所有输出都限制在管道中。
我想知道是否有任何解决方法,以便我可以通过管道传输函数的输出quickedit
。次优的选择是启动一个单独的编辑器,比如 sublime text,但我真的想留在终端中。
答案1
vipe
是一个用于编辑管道的程序:
command1 | vipe | command2
您将获得一个具有完整输出的编辑器,当您退出时,内容将通过管道command1
传递到。command2
在这种情况下,没有command1
.所以,你可以这样做:
: | vipe | pandoc -o foo.pdf
或者:
vipe <&- | pandoc -o foo.pdf
vipe
获取EDITOR
和VISUAL
变量,因此您可以使用它们来打开 Vim。
如果您还没有安装,vipe
可以在moreutils
软件包中找到;sudo apt-get install moreutils
,或者任何与你的口味相当的东西。
答案2
您可以在 Vim 中执行此操作:
:w !pandoc -o file.pdf
或者甚至将缓冲区写入复杂的管道中:
:w !grep pattern | somecommand > file.txt
然后你可以退出Vim而不保存:
:q!
vi
但是,考虑到您的具体用例,使用命令行编辑器可能有更好的解决方案。假设您使用bash
:
set -o vi
这会将您的键绑定设置为vi
.因此,您可以vi
通过按 然后<Esc>
键入vi
诸如x
、等命令,使用基本键绑定在命令行上直接编辑命令。cw
(您可以按 回到插入模式i
。)
更好,并且与这个问题更相关,您可以打开 Vim 直接创建命令行内容。 只需键入<Esc>v
,您就会得到一个空的 Vim 缓冲区。当你保存并退出时,是在命令行上输入命令,它会立即运行。这比直接在命令行上编辑要灵活得多,因为如果需要,您可以编写整个迷你脚本。
因此,例如,如果您想编写一些棘手的文本并立即通过管道将其输入 pandoc,您只需输入:
<Esc>v
然后编辑 Vim 缓冲区,直到出现如下内容:
cat <<EOF | pandoc -o file.pdf
stuff for pandoc
more stuff for pandoc
EOF
然后保存并退出(使用:x
),整个过程将作为 shell 命令运行。
它还可以在 shell 的命令历史记录中找到。
答案3
在管道中运行
尝试:
quickedit() ( trap 'rm ~/temp$$' exit; vim ~/temp$$ >/dev/tty; cat ~/temp$$ )
关键是,要能够vim
正常使用,vim
需要stdout作为终端。我们在这里通过重定向来实现这一点>/dev/tty
。
为了安全起见,我将临时文件放在用户的主目录中。有关这方面的更多信息,请参阅格雷格的常见问题解答问题 062。这样就无需使用晦涩的文件名。
例子:
打开后vim
,我键入This function succeeded.
并保存文件。屏幕上的结果如下所示:
$ quickedit | grep succeeded
This function succeeded.
即使 的输出quickedit
被重定向到管道,vim
仍然可以正常工作,因为我们已经给了它直接访问/dev/tty
.
从 vim 中运行程序
正如我在评论中提到的,vim 可以通过管道将文件传递给命令。例如,在 vim 中发出命令:w !pandoc -o file.pdf
(注意:w 和 ! 之间的空格至关重要)。
答案4
vim、vi、vile、emacs 都支持将其缓冲区甚至缓冲区片段(例如行选择)通过管道传输到过滤器和命令中。它非常强大,可以帮助您编辑文件(因为经典实用程序成为编辑助手),也可以在编辑器中执行任务,使用文本文件来记住通过光标选择或移动等执行的完整命令。这个!
角色是典型的触发因素。阅读 vi 手册并查找此条目。通过便携式定制配置,此类编辑器成为方便的越野工具包,尽管网络或图形功能较差,但仍可使用,并且随着时间的推移(生命周期)保持稳定。他们值得深入学习,其中一位可能会成为你最好的朋友。