如何调用 vim 编辑器和管道输出到 bash

the*_*ith 39 vim pipe stdout

有时我需要编写文本,然后将该文本通过管道传输到另一个命令中。我通常的工作流程是这样的:

vim
# I edit and save my file as file.txt
cat file.txt | pandoc -o file.pdf # pandoc is an example 
rm file.txt
Run Code Online (Sandbox Code Playgroud)

我发现这很麻烦并且正在寻求学习 bash 脚本我想通过编写一个命令来使这个过程变得更加简单,该命令会触发打开一个编辑器,当编辑器关闭时将编辑器的输出通过管道传送到 stdout。然后我就可以将命令作为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
Run Code Online (Sandbox Code Playgroud)

我很快遇到的问题是,当我做类似quickedit | commandvim 之类的事情时,它本身无法用作编辑器,因为所有输出都被限制在管道中。

我想知道是否有任何解决方法,以便我可以通过管道传输quickedit函数的输出。次优的选择是启动一个单独的编辑器,比如 sublime text,但我真的想留在终端中。

mur*_*uru 47

vipe 是一个用于编辑管道的程序:

command1 | vipe | command2
Run Code Online (Sandbox Code Playgroud)

您将获得一个具有完整输出的编辑器command1,当您退出时,内容将通过command2管道传递给。

在这种情况下,没有command1. 所以,你可以这样做:

: | vipe | pandoc -o foo.pdf
Run Code Online (Sandbox Code Playgroud)

或者:

vipe <&- | pandoc -o foo.pdf
Run Code Online (Sandbox Code Playgroud)

vipe获取EDITORVISUAL变量,因此您可以使用它们来打开 Vim。

如果你还没有安装它,vipe可以在moreutils包中找到它;sudo apt-get install moreutils,或者任何你喜欢的口味。

  • 对于已经到达此处的 Mac 用户:Homebrew 中提供了“moreutils”。 (3认同)

Wil*_*ard 24

您可以在 Vim 中执行此操作:

:w !pandoc -o file.pdf
Run Code Online (Sandbox Code Playgroud)

或者甚至将缓冲区写入复杂的管道:

:w !grep pattern | somecommand > file.txt
Run Code Online (Sandbox Code Playgroud)

然后你可以不保存就退出 Vim:

:q!
Run Code Online (Sandbox Code Playgroud)

但是,考虑到您的特定用例,将其vi用作命令行编辑器可能有更好的解决方案。假设您使用bash

set -o vi
Run Code Online (Sandbox Code Playgroud)

这会将您的键绑定设置为vi. 所以,你可以直接使用基本的命令行编辑命令vi键绑定按<Esc>,然后键入vi如命令xcw等等。(您可以通过按回到插入模式i。)

更好,与这个问题更相关的是,您可以打开 Vim 直接创建命令行内容。 只需键入<Esc>v,您将获得一个空的 Vim 缓冲区。当您保存并退出时,这您命令行上的命令,它会立即运行。这比直接在命令行上编辑要灵活得多,因为您可以根据需要编写整个迷你脚本。


因此,例如,如果您想编写一些棘手的文本并立即将其通过管道传输到 pandoc,您只需键入:

<Esc>v
Run Code Online (Sandbox Code Playgroud)

然后编辑 Vim 缓冲区,直到你有类似的东西:

cat <<EOF | pandoc -o file.pdf
stuff for pandoc
more stuff for pandoc
EOF
Run Code Online (Sandbox Code Playgroud)

然后保存并退出(使用:x),整个过程将作为 shell 命令运行。

它也将在您的 shell 的命令历史记录中可用。


Joh*_*024 19

在管道中运行

尝试:

quickedit() (  trap 'rm ~/temp$$' exit; vim ~/temp$$ >/dev/tty; cat ~/temp$$ )
Run Code Online (Sandbox Code Playgroud)

关键是,要想vim正常使用,vim需要以stdout为终端。我们在这里使用 redirect 来完成>/dev/tty

为了安全起见,我将临时文件放在用户的主目录中。有关这方面的更多信息,请参阅Greg 的常见问题解答 062。这消除了使用晦涩文件名的需要。

例子:

vim打开时,我输入This function succeeded.并保存文件。屏幕上的结果如下所示:

$ quickedit | grep succeeded
This function succeeded.
Run Code Online (Sandbox Code Playgroud)

即使 的输出quickedit被重定向到管道,vim仍然可以正常工作,因为我们已经给了它直接访问/dev/tty.

在 vim 中运行程序

正如我在评论中提到的,vim 可以通过管道将文件传递给命令。例如,从 vim 中发出命令:w !pandoc -o file.pdf(注意:w 和 ! 之间的空格是必不可少的)。

  • 很好的答案。这个直接解决了用户的问题,并提供了一个快速而优雅的解决方案:将 vim 重定向到 /dev/tty!简单的! (2认同)

Dop*_*oti 9

确保将vim其设置为您的默认编辑器(例如export EDITOR=vim在您的.bash_profile或 中.bashrc。然后,在任何提示下,您可以键入Ctrl-X后跟Ctrl- E。这将在您配置的编辑器中打开您当前的命令行(例如vim)。进行编辑、保存和退出,并且该命令将被执行,就像您在命令行中键入它一样,包括管道等。