!$ を前のコマンドの最後の単語に置き換える bash エイリアスを記述するにはどうすればよいですか?

!$ を前のコマンドの最後の単語に置き換える bash エイリアスを記述するにはどうすればよいですか?

いくつかのビルド成果物を別のディレクトリにコピーする という名前のスクリプトがあります。その後、コピー先のディレクトリでcpodin編集します。SHA1SUM

例えば:

cpodin /foo/bar/baz
vim !$/SHA1SUM

fixsha後者のコマンドを、引数を取らず、SHA1SUM前のコマンドの最後の引数で指定されたディレクトリを編集するエイリアスにするにはどうすればよいでしょうか?

alias fixsha='vim !$/SHA1SUM'

!$/SHA1SUM代わりに編集が試行されます/foo/bar/baz/SHA1SUM

答え1

Bashはエイリアス展開後に履歴展開を行わないので、 を使って明示的に行う必要がありますhistoryBash 履歴ビルトイン以下に抜粋します。

history -ps args

  • -p
    履歴置換を実行する引数結果を履歴リストに保存せずに、標準出力に表示します。
  • -s
    引数は、履歴リストの末尾に単一のエントリとして追加されます。

のエイリアスはalias fixsha='vim $(history -p !$)/SHA1SUM'ほとんどの場合機能しますが、!$空白を含むパスに展開された場合は意図したとおりに機能しません。パス引数を二重引用符で囲むと、空白でのエスケープが保護され、vim "/foo/bar\ baz/SHA1SUM"目的の またはvim /foo/bar\ baz/SHA1SUMそれと同等のではなく が結果として表示されますvim "/foo/bar baz/SHA1SUM"

したがって、明示的な履歴展開に加えて、eval引用の 1 つのレイヤーをアンラップすることも必要です。

alias fixsha='eval vim "$(history -p !$)/SHA1SUM"'

注記:上記のエイリアス定義の二重引用符が不要であることに驚かれるかもしれません。これは、と の展開された値の間に空白がなく!$/SHA1SUMbash の単語分割がトリガーされないためです。ただし、単一の引数に展開するという意図を強調するために、二重引用符があるのは良いと思います。

関連情報