PROMPT_COMMANDで最後のコマンドが空かどうかを通知


12

bashで、PROMPT_COMMAND内から、ユーザーが「return」キーを押しただけでコマンドを入力しなかったかどうかを確認する方法はありますか?

回答:


7

履歴番号が増加していないか確認してください。キャンセルされたプロンプトまたはユーザーが押したばかりのプロンプトはEnter、履歴番号をインクリメントしません。

履歴番号は変数HISTCMDで使用できますが、では使用できませんPROMPT_COMMAND(必要なのは実際には前のコマンドPROMPT_COMMANDの履歴番号なので、それ自体を実行するコマンドには履歴番号がないためです)。の出力から番号を取得できますfc

prompt_command () {
  HISTCMD_previous=$(fc -l -1); HISTCMD_previous=${HISTCMD_previous%%$'[\t ]'*}
  if [[ -z $HISTCMD_before_last ]]; then
    # initial prompt
  elif [[ $HISTCMD_before_last = "$HISTCMD_previous" ]]; then
    # cancelled prompt
  else
    # a command was run
  fi
  HISTCMD_before_last=$HISTCMD_previous
}
PROMPT_COMMAND='prompt_command'

履歴(HISTCONTROL=ignoredupsまたはHISTCONTROL=erasedups)で重複のスカッシュをオンにした場合、2つの同じコマンドを続けて実行した後、空のコマンドが誤って報告されます。


ありがとう、ジル。ここに何か欠けています。PROMPT_COMMAND = 'echo hello'は機能しますが、リテラル関数の最初の行に 'echo hello'を配置しても機能しないため、これは実行されないようです。HISTCMD_previousとHISTCMD_PREVIOUSの問題の可能性があると思いましたが、サイコロはありません。私は突っ込み続けますが、あなたのbash fuは明らかに私のリーグを超えているので、コメントします。
ユーザー、

@user私はより多くのタイプミスを修正しました、特に${HISTCMD_previous%%$'[\t ]'*}ビットが欠落していて$'…'`, タブまたはスペースの後ではなくt`またはスペースの後に切り捨てられましたが、bashはタブを印刷します。
Gilles「SO-邪悪なことをやめなさい」

1
このソリューションは、重複が履歴に保存されているという前提に基づいています(これは私にはオフです)。したがって、重複は履歴に保存されませんが、このソリューションは繰り返しコマンドに対して期待どおりに機能しません。
Schlimmchen 2017年

4

回避策はありますが、いくつかの要件があります。

$HISTCONTROLすべてのコマンドを保存するように設定する必要があります。また、重複とスペースも保存します。だから設定:

HISTCONTROL=

次に、呼び出す関数を次のように定義します$PROMPT_COMMAND

isnewline () {
  # read the last history number
  prompt_command__isnewline__last="$prompt_command__isnewline__curr"
  # get the current history number
  prompt_command__isnewline__curr="$(history 1 | grep -oP '^\ +\K[0-9]+')"
  [ "$prompt_command__isnewline__curr" = "$prompt_command__isnewline__last" ] && \
    echo "User hit return"
}

次に、$PROMPT_COMMAND変数を設定します。

PROMPT_COMMAND="isnewline"

出力を確認します。

user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$ 

ここで一時ファイルを使用している理由がわかりません。変数lastは、の呼び出しからisnewline次の呼び出しまで保持されます(prompt_command__isnewline__last衝突を避けるために、より一般的でない名前のみを選択してください)。
Gilles「SO-邪悪なことをやめよう」

@ギレスあなたは正しい、私はそれを変更しました、あなたの提案に感謝します
混沌

ありがとう、混乱。以下についても同じ考え方を使用しましたが、これは解析が少し簡単です。 HISTCONTROL="" function last_was_blank { local last_command="$(history 1)" if [[ "$last_was_blank_PREVIOUS_LINE" = "$last_command" ]] ; then echo "true" else echo "false" fi export last_was_blank_PREVIOUS_LINE="$last_command" } PROMPT_COMMAND=last_was_blank
ユーザー

1

それ自体それを行う方法がわかりません。しかし、以下を使用することで同じ効果を得ることができます

トラップsome_command_or_functionデバッグ

これにより、some_command_or_functionコマンドを実行するたびにが呼び出されます。トリッキーなのは、ヒットしただけでは呼び出されEnterないことです。PROMPT_COMMANDが定義されていない限り、ヒットするとPROMPT_COMMAND Enterが呼び出され、それによってトラップがトリガーされます。

おそらく、希望する結果を得る最も簡単な方法は、PROMPT_COMMANDを使用する代わりにデバッグトラップ関数を定義することです。しかし、あなたが望んでいる結果がわからないので、私にはわかりません。を押しただけで何かが発生しEnter、コマンドを入力したときに別の/追加の何かが発生したい場合は、(AFAIK)デバッグトラップとPROMPT_COMMANDを使用する必要があります。 2つのメカニズムをうまく連携させる方法については、この回答と  これを参照してください。


0

(コメントの追加が許可されていれば、これは承認された回答へのコメントになります...)@schlimmen、次のHISTTIMEFORMATような値に設定してHISTTIMEFORMAT='%F %T '、保存して比較できhistory 1ます。これは、erasedupsを使用すると、少なくとも(おそらく繰り返される)最後のコマンドのタイムスタンプが毎回変更されるためです---およびHISSTIMEFORMAT適切に設定されているhistory 1と、タイムスタンプが(とは異なりfc)表示され、繰り返されるコマンド間でも異なるためです。

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