vimエディターを呼び出し、出力をbashにパイプする方法


34

テキストを作成して、そのテキストを別のコマンドにパイプする必要がある場合があります。私の通常のワークフローは次のようになります。

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スクリプトを学習しようとしているので、エディターを起動するコマンドを作成し、エディターがパイプを閉じるとエディターの出力を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

私がすぐに出くわした問題は、quickedit | commandvim自体のようなことをすると、すべての出力がパイプに制約されるため、エディターとして使用できないことです。

quickedit関数の出力をパイプできるように、これに対する回避策があるかどうか疑問に思っています。準最適な代替案は、崇高なテキストなどの別のエディターを起動することですが、私は本当にターミナルに留まりたいです。


vim内から、コマンドを発行し:w !pandoc -o file.pdfますか?:(間のスペースに注意してくださいwし、!必要不可欠である。)
John1024

わかりました-それは素晴らしいです。vim自体からvim出力をパイプできるとは知りませんでした。これは私の目的に役立ちますが、私の将来の知識のために、問題を解決することを意図したとおりに正確に解決することは可能ですか?
theideasmith

関数を投稿できますか?あなたがすぐに遭遇した問題について話すとき、あなたは何を意味しますか(最後の2番目の段落)?わかりません。
ルーカス

5
余談ですが、安全でない方法で再発明するのではなく、使用mktempする必要があります
ワイルドカード

新しいbashユーザーとして、mktempを再発明することのセキュリティ上の危険性は何ですか?
theideasmith

回答:


42

vipe パイプラインを編集するためのプログラムです。

command1 | vipe | command2

の完全な出力を備えたエディターを取得し、command1終了すると、コンテンツがcommand2パイプ経由で渡されます。

この場合、ありませんcommand1。だから、あなたはすることができます:

: | vipe | pandoc -o foo.pdf

または:

vipe <&- | pandoc -o foo.pdf

vipe上のピックアップEDITORVISUAL変数なので、あなたはそれがVimを開くために取得するために、これらのを使用することができます。

インストールされていない場合vipeは、moreutilsパッケージで利用可能です。sudo apt-get install moreutils、またはあなたのフレーバーに相当するものは何でも。


1
ここに到着したMacユーザーの場合:moreutilsHomebrewで利用可能です。
-vergenzt

FreeBSDユーザーの場合:pkg(8)をmoreutils介してインストールできます。
マテウスピオトロフスキ

20

Vim内からこれを行うことができます。

:w !pandoc -o file.pdf

または、バッファを複雑なパイプラインに書き込むこともできます。

:w !grep pattern | somecommand > file.txt

そして、保存せずにVimを終了できます:

:q!

ただし、特定のユースケースを考慮するviと、コマンドラインエディタとして使用することにより、おそらくより良いソリューションがあります。あなたが使用すると仮定bash

set -o vi

これにより、キーバインドがに設定されますvi。右の基本的なコマンドラインで、あなたのコマンドを編集することができますので、vi押して、キーバインド<Esc>してから入力するviなどのコマンドxcw(あなたが押して挿入モードに戻って取得することができ、などi。)

さらに良いことに、この質問により関連性が高い場合はVimを開いてコマンドラインコンテンツを直接作成できます。 入力するだけで<Esc>v、空のVimバッファーが得られます。保存して終了すると、それコマンドラインのコマンドになり、すぐに実行されます。これは、必要に応じてミニスクリプト全体を作成できるため、コマンドラインで直接編集するよりもはるかに柔軟性があります。


そのため、たとえば、トリッキーなテキストを書いてすぐにpandocにパイプしたい場合は、次のように入力するだけです。

<Esc>v

次に、次のようなものになるまでVimバッファーを編集します。

cat <<EOF | pandoc -o file.pdf
stuff for pandoc
more stuff for pandoc
EOF

次に(を使用して:x)保存して終了すると、すべてがシェルコマンドとして実行されます。

また、シェルのコマンド履歴でも利用できます。


1
あなたがEmacsのキーバインディングを維持したい場合は、まだ設定して、編集コマンドラインにVimを使用することができるEDITORように環境変数をvim、プレスCtrl-Xに続いてCtrl-E、コマンドラインを編集中。
アンソニーG-モニカの正義

18

パイプラインで実行する

試してください:

quickedit() (  trap 'rm ~/temp$$' exit; vim ~/temp$$ >/dev/tty; cat ~/temp$$ )

重要なのは、vim正常に使用できるようにするには、vim標準出力を端末にする必要があるということです。ここでリダイレクトを使用してこれを実現します>/dev/tty

セキュリティのために、一時ファイルをユーザーのホームディレクトリに配置します。詳細については、GregのFAQ Question 062を参照してください。これにより、あいまいなファイル名を使用する必要がなくなります。

例:

vim開いたらThis function succeeded.、ファイルを入力して保存します。画面上の結果は次のようになります。

$ quickedit | grep succeeded
This function succeeded.

の出力はquickeditパイプラインにリダイレクトされますが、vimに直接アクセスできるようにしているため、通常どおり機能し/dev/ttyます。

vim内からプログラムを実行する

コメントで述べたように、vimはファイルをコマンドにパイプすることができます。たとえば、vim内からコマンドを発行します:w !pandoc -o file.pdf(注:wと!の間のスペースは必須です)。


2
いい答えだ。これはユーザーの質問に直接対処し、迅速でエレガントなソリューションを提供します:vimを/ dev / ttyにリダイレクトします!シンプル!
マイクS

Zshを使用しています。trap '...' exit失敗しますがtrap '...' EXIT、動作しているようです。トラップについてはあまり知りませんが、一時ファイルの一般的なアプローチはを使用することmktmp [--suffix=...]です。また、vim <outfile> -c '...' >/dev/ttyファイルがロードされるまで通常どおり実行され、その後:wq、編集フェーズをスキップするかどうかなど、指定されたコマンドチェーンを実行します。私も使用set | grep -a EXITして見つけましたsignals=(EXIT ... DEBUG)
ジョンP

5

それvimがデフォルトのエディターとして設定されていることを確認してください(例えばexport EDITOR=vim.bash_profileまたはで.bashrc。その後、任意のプロンプトでCtrl-にX続けてCtrl-を入力できEますvim)。終了すると、コマンドは、パイプラインなどを含めてコマンドラインで入力したかのように実行されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.