Bash と Zsh には、Enter キーを押すとエイリアスが展開される内容をエコーするモードがありますか?

Bash と Zsh には、Enter キーを押すとエイリアスが展開される内容をエコーするモードがありますか?

例えば、私が

alias dbmigrate='rails db:migrate'

シェルに入力するときに、Bash と Zsh で設定するモードまたは簡単な方法はありますか:

$ dbmigrate  # press Enter

実行する前に、エイリアスが展開される内容をエコーし​​ますか?

答え1

バッシュalias-expand-line、およびreadline 関数がありますhistory-and-alias-expand-lineが、デフォルトではどのキーにもバインドされていません。 自分でバインドすることができます。たとえばControl-T、 のようにです。

bind '"\C-T": history-and-alias-expand-line'

バインドしようとするとEnter面倒なことになります。なぜなら、押すたびにEnterコマンドが実行されるわけではないからです (たとえば、パイプラインが不完全な場合など)。

トラップもありますDEBUGが、コマンドが実際にユーザーによって入力されたかどうか(たとえば、から開始されたか、またはPROMPT_COMMANDのコマンド置換から開始されたかPS1どうか)、およびエイリアス展開されたかどうかを判断するのは困難です。ただし、印刷しても問題ない場合は、どれでも実行される前のコマンド:

trap 'echo "> $BASH_COMMAND"' DEBUG

bash$ pwd
> pwd

翻訳preexecユーザーが入力したコマンドと異なる場合に、展開されたコマンドを出力する関数を定義するだけで済みます。

preexec(){ [ $1 != $2 ] && print -r "> $2" }

zsh$ j
> jobs

ただし、エイリアスを強制的に展開すると、一部のエイリアス + 履歴トリックが正しく機能しないことに注意してください。たとえば、、などをエスケープせずにcなどの計算を実行するための bash のエイリアスがあります。c 3.17 * 4.2*(

alias c='_c=$(fc -nl -0); bc -l <<<${_c#*c} #'

readlineがそれを展開すると、履歴の現在の行(によって返される行fc -nl -0)は拡大、元のコマンドではなく、すべてが崩壊します。

答え2

エイリアスは単なる置換です。コマンドを実行する前にメッセージを出力するなど、より高度な操作を行う場合は、より強力なもの、つまり関数が必要です。定義をエイリアス定義のようにしたい場合は、関数を定義する関数を定義できます。

function verbose_alias {
  local name=${1%%=*} expansion=${1#*=}
  eval "function $name {
    printf >&2 '%s is an alias for %s\\n' \"$name\" \"$expansion\";
    $expansion \"\$@\";
  }"
}
verbose_alias dbmigrate='rails db:migrate'

答え3

POSIXでは、set指示このオプションを持つ

-x

   シェルは、コマンドを展開した後、それを実行する前に、各コマンドのトレースを標準エラーに書き込みます。トレースをオフにするコマンドがトレースされるかどうかは指定されていません。

https://pubs.opengroup.org/onlinepubs/009604499/utilities/set.html

set -xしたがって、互換性のあるシェルであれば、またはを使用できますset -o xtrace。bash では、man ページでこれを参照できます。

-x

   各単純コマンド、for コマンド、case コマンド、select コマンド、または算術 for コマンドを展開した後、PS4 の展開された値を表示し、その後にコマンドとその展開された引数または関連する単語リストを表示します。

xtrace

   と同じ-x

参考:

zshにも同様のオプションがあり、set組み込み

エクストレース-x、ksh: -x

   実行されたコマンドとその引数を出力します。

https://linux.die.net/man/1/zshoptions

-xスクリプトやコマンドの実行中にオプションを指定することもできます

bash -x -c "echo This will be printed before running; ll"
bash -x script-to-be-debugged.sh
zsh -x -c "...; 3; md did-you-see-the-aliases"
zsh -x buggy-script.sh

各プロンプトの前後に実行されるコマンドも展開されるため、gitPS1で変数を使用する場合など、多くの状況では望ましくない可能性があることに注意してください。私のクリーンなUbuntu VMでは、実行中のコマンドのみが出力されます。

参照set -xをするのですか?

もう一つのオプションは、印刷前に変数を展開しないかset -v、である。set -o verbose

答え4

そのようなヘルプは、bash ではデフォルトでは利用できません。

デフォルトで使用できる 2 つの関連機能は次のとおりです。

  • shopt -s histverify

設定され、readline が使用されている場合、履歴置換の結果はすぐにはシェル パーサーに渡されません。代わりに、結果の行が readline 編集バッファーにロードされ、さらに変更できるようになります。

これは、 が押されたときのアクションの部分に対応しますEnterが、コマンド ラインでの履歴展開のみです。例:

$ shopt -s histverify
$ echo "this is a test"
This is a test
$ echo !!
$ echo echo "this is a test"  <---- expanded by the simple use of enter!! 
  • 読み込まれた行shell-expand-line

シェル展開ライン (MCe)

シェルと同じように行を展開します。これにより、エイリアスと履歴の展開、およびすべてのシェル ワードの展開が実行されます。履歴の展開の説明については、以下の履歴の展開を参照してください。

これはまさにあなたが求めていることですが、それを実現するための鍵はCtrl- Alt-e

申し訳ありませんが、 enter と executes で機能する解決策は知りませんshell-expand-line

関連情報