arglistを設定するためにbacktick-expansionを使用する方法は?


11

ヘルプから:help backtick-expansion

On Unix and a few other systems you can also use backticks for the file name
argument, for example:
    :next `find . -name ver\\*.c -print`
    :view `ls -t *.patch  \| head -n1`
The backslashes before the star are required to prevent the shell from
expanding "ver*.c" prior to execution of the find program.  The backslash
before the shell pipe symbol "|" prevents Vim from parsing it as command
termination.

ヘルプから取得したコマンドを入力すると、エラーが発生します。

:next `find . -name ver\\*.c -print
E79: Cannot expand wildcards  

ヘルプの例で1つではなく2つのバックスラッシュを使用するのはなぜですか、なぜ機能しないのですか?

次の作業:

  • findプログラムの前にシェルによってスターが拡張されるのを防ぐ2つのバックスラッシュの1つを削除すると、次のようになります。

    :next `find . -name ver\*.c -print`
    
  • 両方のバックスラッシュを削除し、パターンを一重引用符で囲むとver*.c

    :next `find . -name 'ver*.c' -print`
    

これまでのルールは
、シェルコマンドにスターが含まれていて、コマンドの前にシェルで展開したくない場合は、その前にバックスラッシュを1つ置くか、パターンを一重引用符で囲みます

しかし、ヘルプは別の例を示します:

:view `ls -t *.patch  \| head -n1`

このコマンドは変更せずに機能し、一重引用符もバックスラッシュも不要です。
私がそれが機能する理由は、lsコマンドが(コマンドの-name引数とは逆にfind)複数のファイル引数を受け入れ、シェルの展開に問題がないためだと思います*.patch

それでは、私は拡張子を持つすべてのファイルを探したいとしましょう.conf内部の/etcフォルダやパイプの出力findgrep文字列を含む唯一のマッチを取得しますinput
シェルでは、任意の作業ディレクトリから、次のように入力します。

find /etc -name '*.conf' | grep input

そしてそれはうまくいくでしょう。

vimでは、同じコマンドを入力してバッククォートを囲み、パイプ記号の前にバックスラッシュを付けて、vimがコマンド終了と解釈しないようにします。

:next `find /etc -name '*.conf' \| grep input`

そしてそれは機能します。

ここで、パイプとなしで同じコマンドを入力するとgrep input、エラーが発生します。

:next `find /etc -name '*.conf'`
E79: Cannot expand wildcards

一重引用符で星を保護しているのに、この場合エラーが発生するのはなぜですか?
そして、なぜ今エラーが発生していますが、直前にパイプとgrep input

理解を試みるために、より簡単なコマンドを考え出しました。

find . -name '*.conf'

.conf作業ディレクトリで拡張子が付いたすべてのファイルを検索します。コマンドはシェルで機能します。

vimでテストするには、次のように入力しました:next `find . -name '*.conf'`
。この場合、ドットはvimセッションを起動してからの:pwdホームディレクトリであるExコマンドで表示される現在の作業ディレクトリを表し/home/usernameます。

現在の作業ディレクトリで検索を要求すると機能するのに、次のような任意のフォルダーで検索を要求すると機能しないのは/etcなぜですか?

ここで、vim Exコマンド/home/usernameを使用/etcして作業ディレクトリをからに変更し、:cd /etc以前と同じコマンドを再試行すると、再びエラーになります。

:next `find . -name '*.conf'`
E79: Cannot expand wildcards

ホームフォルダーにいるときは同じコマンドが機能するのに、ホームフォルダーにいるときは機能しないのはなぜ/etcですか。

いくつかのロジックがあると確信していますが、それを見つけることができません。

arglistに任意のシェルコマンド(スター、パイプを含み、任意の作業ディレクトリから任意のディレクトリを検索する)を入力するための一般的で正しい構文は何ですか?

私はvimバージョン7.4.942を使用していますが、zshがデフォルトのシェルです。これらのコマンドを、vim -u NORC -Nbashとzshからの初期化()を最小限にしてテストしました。

zshではなくbashを呼び出すようにvimを構成する必要がありますか?


引数として渡されたすべてのファイルでvimを起動しようとしたのでしょうか。私のような平均何か:vim $(find . -name ver*.c)
ヴラドGURDIGA

@VladGURDIGA私は試したし、彼らは、シェルから予想されるようにすべての作業:vim $(find . -name ver\*.c -print)vim $(ls -t *.patch | head -n1)vim $(find /etc -name '*.conf' | grep input)vim $(find /etc -name '*.conf')vim $(find . -name '*.conf')
サギノー

@VladGURDIGAしかし、私は通常1つしか持っていないので、現在のセッションを終了せずにarglistに入力する方法を知りたいです。シェル内を移動してファイルのグループを検索し、それらをVimサーバーに送信することもできます(引数は--remotevi.stackexchange.com / a / 5618/4939を参照)。しかし、その方法を知りたいと思っています。現在のセッションから直接実行してください。それが不可能な場合は問題ありませんが、ヘルプを読んだ後は、実行できるようです。もしそうなら、なぜvimが同様のコマンドに対して非常に異なる反応をするのかを理解したいと思います。
saginaw 2015

ちょっと、最初のサンプルコマンドでは、クロージングバックティックがないようです。;)それはさておき、ここで説明するように、シェルの展開を防ぐために、ヘルプの例では1つではなく2つのバックスラッシュを使用していると思います:unix.stackexchange.com/q/104260/23669
Vlad GURDIGA、2015

機能しfind /etc -name '*.conf'ない場合、そのコマンドからいくつかの面白い名前が出てくると思います。これが、をパイプで通しgrepたときに機能した理由かもしれません。
Vlad GURDIGA、2015

回答:


6

まだbacktick-expansionを使用してarglistに任意のシェルコマンドを入力する方法はわかりませんが、回避策を見つけました。

から:help `=

You can have the backticks expanded as a Vim expression, instead of as an
external command, by putting an equal sign right after the first backtick,
e.g.:
    :e `=tempname()`
The expression can contain just about anything, thus this can also be used to
avoid the special meaning of '"', '|', '%' and '#'.  However, 'wildignore'
does apply like to other wildcards.

したがって、次のようなシェルコマンドを直接展開する代わりに:

:args `shell command`

シェルコマンドをVim関数に送信しsystemlist()、式レジスタ=を使用して、次のように結果の式を展開できます。

:args `=systemlist("shell command")`

いくつかのキーストロークを保存するために、vimrcに次のExコマンドを定義しました(:PAPopulate Arglist用)。

command! -nargs=1 PA args `=systemlist(<q-args>)`

そして、それをさまざまなシェルコマンドでテストしました:

:PA find . -name ver\*.c -print 2>/dev/null
:PA find . -name 'ver*.c' -print 2>/dev/null
:PA ls -t *.patch  | head -n1
:PA find /etc -name '*.conf' 2>/dev/null | grep input
:PA find /etc -name '*.conf' 2>/dev/null
:PA find . -name '*.conf' 2>/dev/null

これまでのところ、期待どおりに動作し、コマンドはシェルと同じように入力できます(たとえば、パイプをエスケープする必要はありません)。
直接バックティック展開よりも一貫性と信頼性が高いようです。

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