command_not_found_handle
私は間違ったコマンドが与えられたときにユーザーに最も同じコマンドを意図したものかどうかを尋ねる独自の関数を作成しようとしています。ユーザーが提案を受け入れたら、履歴から最後のコマンド(無効なコマンド)を削除し、選択したコマンドを追加する必要があります。しかし、うまくいきません。
これは私のコードです
command_not_found_handle(){
....
# replace the previous wrong command with the correct one in bash history
history -d -1
history -s "$command $@"
}
無効なコマンドを入力して提案のいずれかを選択した場合、履歴は変更されません。しかし、私が直接関数を呼び出すと
command_not_found_handle wrong_command
履歴を更新し、履歴を削除し、wrong_command
新しい履歴を追加します。
history
関数内でコマンド(記録リストを返す)を呼び出して、どちらの場合も関数に履歴への読み取りアクセス権があることを確認しました。ただし、最初のケースでは歴史に記録することはできません。
答え1
この機能を直接使用することはできませんcommand_not_found_handle
。
によるとman bash
:
検索に失敗すると、シェルはcommand_not_found_handleという定義されたシェル関数を検索します。関数が存在する場合は、元のコマンドと元のコマンドの引数を引数として別々の実行環境で呼び出されます。
history
したがって、すべての変更などがvariables
失われます。たとえば、次の項目を含めます~/.bashrc
。
val=10
command_not_found_handle() {
echo Val is $val
val=50
echo Val now is $val
}
存在しないコマンドを実行する前に、次の値を印刷してくださいval
。
(bash shell)> echo $val
#Output
10
ls4
現在存在しないコマンド(印刷など)を入力すると、val
次のような結果が得られます。
(bash shell)> ls4
#Output
Val is 10
Val now is 50
(bash shell)> echo $val
#Output
10
上記のように、最終値はですが、50
完了後のcommand_not_found_handle
最終値はです10
。
これはデフォルトでサブシェルを実行しているために発生しますbash
。以下を使用して確認できます。
val=10
command_not_found_handle() {
echo Val is $val
val=50
echo Val now is $val
echo "Parent bash PID: $$"
echo "BASH PID: $BASHPID"
#echo $BASH_SUBSHELL #NOTE If I'm not wrong this should print `1` but
# it prints 0 (which is the current level of the bash parent shell). I'm not sure why.
echo -e "\nUsing ps\n"
ps
}
存在しないコマンドを実行すると、次の結果が再表示されます。
(bash shell)> ls4
#Output
Val is 10
Val now is 50
Parent bash PID: 15399
BASH PID: 15420
Using ps
PID TTY TIME CMD
10561 pts/3 00:00:00 zsh
15399 pts/3 00:00:00 bash
15420 pts/3 00:00:00 bash
15421 pts/3 00:00:00 ps
ご覧のとおり、シェルcommand_not_found_handle
で実行していますPID: 15420
。したがって、変数は完了するとval
その値を失います。50
command_not_found_handle
考えられる解決策:
あなたは保存する必要があります正しいこのコマンドはファイルに書き込み、次の3つの方法のいずれかで履歴を変更します。
関数command_not_found_handle
は次のようになります。
command_not_found_handle() {
echo "$1: command not found" >&2
read -p "What did you mean? " cmd
echo -n "$cmd" > '/tmp/cmd.txt'
}
これで、履歴を変更する関数を作成する必要があります。
checkHist(){
[ -f '/tmp/cmd.txt' ] && {
h="$(cat /tmp/cmd.txt)"
history -d -1
history -s "$h"
rm '/tmp/cmd.txt'
}
}
最後に、次の3つのオプションを使用して履歴を簡単に変更できます。
解決策1:変数の使用PROMPT_COMMAND
:
PROMPT_COMMAND='checkHist'
上記のコードを使用すると、命令の実行時に内部の内容(この場合は関数)がPROMPT_COMMAND
実行されます。checkHist
自動的に行われるので、これが最も簡単な方法です。
解決策2:バインディングキー/ショートカット
bind -x '"\C-p":checkHis'
上記のコードを使用してcheckHis
次のコマンドを押すと、関数が実行されます。Ctrl+p
解決策3:短いエイリアスの使用
alias u="checkHist"
u
このエイリアスを使用すると、端末でその文字を使用/入力して履歴を変更できます。