В bash, изнутри PROMPT_COMMAND, есть ли способ узнать, нажал ли пользователь «возврат» и не ввел ли команду?
12
Проверьте, был ли увеличен номер истории. Отмененный запрос или запрос, когда пользователь только что нажал 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
), это приведет к ошибочному сообщению о пустой команде после последовательного выполнения двух одинаковых команд.
${HISTCMD_previous%%$'[\t ]'*}
бит пропускал$'…'
и заканчивал усечением после`,
t` или пробела, а не после табуляции или пробела, но bash печатает табуляцию.Существует обходной путь, но у него есть некоторые требования:
Вам необходимо настроить
$HISTCONTROL
сохранение ВСЕХ команд, а также дубликатов и пробелов. Итак, установите:Теперь определите функцию для вызова как
$PROMPT_COMMAND
:Теперь установите
$PROMPT_COMMAND
переменную:Смотрите вывод:
источник
last
сохраняется от одного вызоваisnewline
к другому (выбирайте только менее общее имя,prompt_command__isnewline__last
чтобы избежать конфликтов).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
Я не знаю способ сделать это, сами по себе . Но вы можете получить тот же эффект, используя
Это заставит
some_command_or_function
вызываться каждый раз, когда вы запускаете команду. Хитрость в том, что он не будет вызываться, если вы просто нажмете Enter- если только у вас не определен PROMPT_COMMAND, в этом случае Enterнажатие вызывает PROMPT_COMMAND, что, в свою очередь, вызывает ловушку.Возможно, самый простой способ достичь желаемого результата - определить функцию отладочной ловушки вместо использования PROMPT_COMMAND. Но я не могу сказать, потому что я не знаю, какой результат вы хотите. Если вы хотите, чтобы что-то происходило, когда вы просто нажимаете Enter, и что-то другое / дополнительное, когда вы набираете команду, тогда (AFAIK) вам нужно использовать отладочную ловушку и PROMPT_COMMAND. Посмотрите этот ответ и этот, чтобы узнать, как эти два механизма хорошо играют вместе.
источник
(Это был бы комментарий к принятому ответу, если бы мне было позволено добавлять комментарии ...) @schlimmen, вы можете установить
HISTTIMEFORMAT
что-то подобное,HISTTIMEFORMAT='%F %T '
а затем сохранить и сравнитьhistory 1
. Это связано с тем, что при erasedups, по крайней мере, метка времени (возможно, повторяющейся) последней команды изменяется каждый раз - и приHISSTIMEFORMAT
соответствующей установкеhistory 1
будет отображаться метка времени (в отличие отfc
), и, таким образом, будет отличаться даже между повторяющимися командами.источник