Czy w bash od wewnątrz PROMPT_COMMAND istnieje sposób, aby stwierdzić, czy użytkownik po prostu nacisnął „return” i nie wprowadził polecenia?
12
Sprawdź, czy numer historii został zwiększony. Anulowany monit lub monit, w którym użytkownik właśnie nacisnął Enter, nie zwiększy numeru historii.
Numer historii jest dostępny w zmiennej HISTCMD
, ale nie jest on dostępny w PROMPT_COMMAND
(ponieważ to, czego chcesz, to w rzeczywistości numer historii poprzedniego polecenia; polecenie, które wykonuje PROMPT_COMMAND
się nie ma numeru historii). Możesz uzyskać liczbę z wyjścia 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'
Zauważ, że jeśli w historii włączyłeś squashowanie duplikatów ( HISTCONTROL=ignoredups
lub HISTCONTROL=erasedups
), to błędnie zgłosi puste polecenie po uruchomieniu dwóch identycznych poleceń kolejno.
${HISTCMD_previous%%$'[\t ]'*}
brakowało bitu$'…'
i skończyło się na skrócie po`,
t` lub spacji zamiast po tabulatorze lub spacji, ale bash drukuje tabulację.Istnieje obejście, ale ma pewne wymagania:
Musisz ustawić
$HISTCONTROL
zapisywanie WSZYSTKICH poleceń, a także duplikatów i spacji. Więc ustaw:Teraz zdefiniuj funkcję do wywołania jako
$PROMPT_COMMAND
:Teraz ustaw
$PROMPT_COMMAND
zmienną:Zobacz wynik:
źródło
last
jest zachowywana od jednego wywołaniaisnewline
do następnego (wybierz mniej ogólną nazwę,prompt_command__isnewline__last
aby uniknąć kolizji).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
Nie wiem, jak to zrobić, per se . Ale możesz uzyskać ten sam efekt, używając
Spowoduje to, że
some_command_or_function
zostanie wywołany za każdym razem, gdy uruchomisz polecenie. Trudne jest to, że nie zostanie wywołane, jeśli tylko uderzysz Enter- chyba że masz zdefiniowany PROMPT_COMMAND, w którym to przypadku naciśnięcie Enterwywołuje PROMPT_COMMAND, co z kolei wyzwala pułapkę.Być może najprostszym sposobem na osiągnięcie pożądanego rezultatu jest zdefiniowanie funkcji pułapki debugowania zamiast używania PROMPT_COMMAND. Ale nie mogę powiedzieć, ponieważ nie wiem, jaki wynik chcesz. Jeśli chcesz, aby coś się wydarzyło po prostu po naciśnięciu Enter, a coś innego / dodatkowego wydarzy się po wpisaniu polecenia, to (AFAIK) musisz użyć pułapki debugowania i PROMPT_COMMAND. Zobacz tę odpowiedź i tę, aby dowiedzieć się, jak sprawić, by oba mechanizmy ładnie ze sobą grały.
źródło
(Byłby to komentarz do zaakceptowanej odpowiedzi, gdybym mógł dodawać komentarze ...) @schlimmen, możesz ustawić
HISTTIMEFORMAT
coś takiego,HISTTIMEFORMAT='%F %T '
a następnie zapisać i porównaćhistory 1
. Jest tak, ponieważ w przypadku skasowanych danych przynajmniej znacznik czasu (ewentualnie powtarzanego) ostatniego polecenia zmienia się za każdym razem --- i przyHISSTIMEFORMAT
odpowiednio ustawionym,history 1
wyświetli znacznik czasu (w przeciwieństwie dofc
), a zatem różni się nawet między powtarzanymi poleceniami.źródło