$_
を表す既存の と同様に、 のエイリアスを作成し、最後から2番目または3番目のコマンドを参照し!-1:$
たいと思います。$__
$___
alias "$__"='!-2:$'
私の では.zshrc.local
、可能であれば、アンダースコアの数に基づいて、n 番目に最後のコマンドの最初の引数を返す zsh 関数を書きたいと思います。
arch linux kernel 5.1.4-arch
zsh 5.7.1 (x86_64-pc-linux-gnu)
答え1
この機能は既に存在します
前のコマンドの最後の単語にアクセスするのには複雑な操作は必要ありません。ESC-.
(ie Alt+ .) またはESC-_
(ie Alt+ _) を押すだけです。これにより、エディターコマンドが呼び出されます。insert-last-word
は、前のコマンド ラインの最後の単語を挿入します。キーをもう一度押すと、その前のコマンド ラインの最後の単語が取得されます。これを繰り返します。押しESC-.
すぎた場合は、 (元に戻す) を使用して、C-_
直前の単語に戻ります。
このコマンドは、vi モードではデフォルトでキーにバインドされていませんが、 を使用してバインドできますbindkey
。
異なる単語を取得するために数値引数を渡すこともできます。正の数値を指定すると右から始まり (1 が最後の単語)、0 または負の数値を指定すると左から始まり (0 は最初の単語で通常はコマンド名、1 はその次の単語で最初の引数など) ます。たとえば、ESC . ESC - ESC 1 ESC .
最後から 2 番目のコマンドの最初の引数を挿入します。
このコマンドには、独自のウィジェットを定義することでさまざまなバリエーションが可能ですzle insert-last-word
。Zshにはcopy-earlier-word
そしてsmart-insert-last-word
そのまま使用しても、コード例として使用しても役立つ場合があります。
本当に 1 つ前のコマンドの最後の単語まで拡張したい場合は$__
、以下にいくつかの解決策を示しますが、まず何が起こっているのかを説明する必要があります。
なぜあなたの試みはうまくいかないのか
まず、あなたが定義しようとしているものを定義していません。は、エイリアス定義が実行された時点でalias "$__"=…
の変数の現在の値の名前を持つエイリアスを定義します。これはおそらく空なので、検索パスで呼び出されるコマンドを検索するwhich__
を実行しています(alias ='!-2:$'
'!-2:$'
=
拡大(ファイル名展開の一部)。 というエイリアスを定義するには、または などを使用して、 を alias コマンドに$__
渡す必要があります。$__
alias '$__'=…
alias \$__=…
第二に、エイリアスはコマンドの位置、つまりコマンドの最初の単語(先行する変数の割り当てやリダイレクトの後)でのみ展開されます。このエイリアスが有用であるためには、グローバルエイリアス:alias -g '$__'=…
3 番目に、エイリアスの展開は履歴の展開の後に行われるため、このエイリアスは何も役に立ちません。
darkstar
darkstar% alias -g '$__'='!-2:$'
darkstar% echo $__
!-2:$
$_
は を「表す」ものではありません!-1:$
。と$_
は、!-1:$
一般的なケースでは同じ情報にアクセスする 2 つの方法です。$_
は の「エイリアス」である!-1:$
、またはその逆に はの「!-1:$
エイリアス」であると言うことができます$_
が、これは一般的な英語の意味で「エイリアス」を使用しており、シェル エイリアスの技術的な意味では使用していません。また、この 2 つが常に同じ値を持つとは限らないため、不正確です。!-1:$
は歴史の拡大(!
)構造は次のように展開される。最後の言葉(:$
)の前のコマンドライン(-1
)。$_
はparameter expansion
パラメータを使用して_
シェルはこれを前のコマンドの最後の引数に設定します。たとえば、1 つの単純なコマンドではないコマンド ラインを実行する場合は違いが生じます。
darkstar% for x in 1 2 3; do echo $x; done
1
2
3
darkstar% echo $_ is not !-1:$
echo $_ is not done
3 is not done
darkstar% echo $_ and !-1:$ are different; echo $_ and !-1:$ are different
echo $_ and done are different; echo $_ and done are different
done and done are different
different and done are different
$__
コマンドごとに定義
定義することができますトラップ機能と呼ばれるTRAPDEBUG
これは各コマンドを実行する前に実行されます。 の現在の値を覚えておいてください$_
(トラップ内の最初のコマンドが を上書きするため、最初にこれを行う必要があることに注意してください_
)。次に、複数のアンダースコア変数を「シフト」します。
darkstar% TRAPDEBUG () { _0=$_; ___=$__; __=$_1; _1=$_0; }
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_,$__,$___
three,two,one
$_1
は と常に同じになるわけではありません$_
。デバッグ トラップは が_
設定される状況とまったく同じ状況で実行されるわけではないためです。ただし、かなり近い値になります。
$__
コマンドラインごとに定義する
登録することができますフック関数コマンドラインを入力する前または入力した後に実行する。この場合、precmd
またはpreexec
これらはそれぞれコマンドの実行前と実行後に実行されます。
preexec_set_underscore_variables () {
___=$__
__=$_1
_1=$historywords[1]
}
preexec_functions+=(preexec_set_underscore_variables)
私が使うhistorywords
_1
コマンドラインから最後の単語を取得します。 はすでに使用されているため、に格納します_
。そして、関数は最後の単語履歴変数を 1 つ「シフト」します。
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_ $__ $___
three two one