Не могу пока комментировать (и это выходит за рамки простой коррекция), поэтому я добавлю это как ответ.
This correction к the accepted answer не совсем работает, когда, например, последняя команда взяла совсем немного времени, чтобы выполнить - вы получите паразитных номера и ;
в вашей команде, например:
2017-07-22 19:02:42 | 3;micro ~/.zshrc && . ~/.zshrc
Это может быть исправлено путем замены sed -re '1s/.{15}//'
в command_part
с немного больше gawk
, который также избегает нас трубопровода:
local command_part="$(gawk "
NR == $line_num_last {
pivot = match(\$0, \";\");
print substr(\$0, pivot+1);
}
NR > $line_num_last {
print;
}" ~/.zsh_history)"
Он также имеет проблемы при deali ng с многострочными командами, где одна из строк начинается с :
. Это может быть (в основном) зафиксировано заменой grep -ane '^:' ~/.zsh_history
на line_num_last
на grep -anE '^: [0-9]{10}:[0-9]*?;' ~/.zsh_history
. Я говорю в основном потому, что команда может содержать строку, соответствующую этому выражению. Скажем,
% naughty "multiline
> command
> ::123;but a command I'm not
> "
Который приведет к затерта записи в ~/.persistent_history
.
Чтобы исправить это, мы должны, в свою очередь, проверить, заканчивается ли предыдущий redord с \
(там могут быть и другие условия, но я не знаком с этим форматом истории), и если да попробовать предыдущий матч ,
_get_line_num_last() {
local attempts=0
local line=0
while true; do
# Greps the last two lines that can be considered history records
local lines="$(grep -anE '^: [0-9]{10}:[0-9]*?;' ~/.zsh_history | \
tail -n $((2 + attempts)) | head -2)"
local previous_line="$(echo "$lines" | head -1)"
# Gets the line number of the line being tested
local line_attempt=$(echo "$lines" | tail -1 | cut -d':' -f1 | tr -d '\n')
# If the previous (possible) history records ends with `\`, then the
# _current_ one is part of a multiline command; try again.
# Probably. Unless it was in turn in the middle of a multi-line
# command. And that's why the last line should be saved.
if [[ $line_attempt -ne $HISTORY_LAST_LINE ]] && \
[[ $previous_line == *"\\" ]] && [[ $attempts -eq 0 ]];
then
((attempts+=1))
else
line=$line_attempt
break
fi
done
echo "$line"
}
precmd() {
local line_num_last="$(_get_line_num_last)"
local date_part="$(gawk "NR == $line_num_last {print;}" ~/.zsh_history | cut -c 3-12)"
local fmt_date="$(date -d @${date_part} +'%Y-%m-%d %H:%M:%S')"
# I use awk itself to split the _first_ line only at the first `;`
local command_part="$(gawk "
NR == $line_num_last {
pivot = match(\$0, \";\");
print substr(\$0, pivot+1);
}
NR > $line_num_last {
print;
}" ~/.zsh_history)"
if [ "$command_part" != "$PERSISTENT_HISTORY_LAST" ]
then
echo "${fmt_date} | ${command_part}" >> ~/.persistent_history
export PERSISTENT_HISTORY_LAST="$command_part"
export HISTORY_LAST_LINE=$((1 + $(wc -l < ~/.zsh_history)))
fi
}
[Это] (http://superuser.com/questions/735660/whats-the-zsh-equivalent-of-bashs-prompt-command) должно помочь с заменой 'PROMPT_COMMAND'. Замена '[[' использование должно выполняться с помощью 'grep -o' или' cut' или аналогичного, но зависит от точного вывода 'history' в zsh. –
@EtanReisner Большое спасибо! Для «PROMPT_COMMAND» ссылка должна быть полезна.Для '[[' part, я только что нашел с помощью команды 'history', bash даст последнюю строку (в данном случае это' history') в последней строке. Но в Zsh команда 'history' не будет возвращать самую новую, она возвращает команду, используемую до' history' в последней строке. Есть идеи? :-) – astroboylrx
Ну, я не вижу причин изобретать колесо. Просто установите 'HISTFILE' и установите' HISTSIZE' и 'SAVEHIST' в некоторые смехотворно большие размеры (мои 100 000, и я не вижу причин сделать их более крупными, так как я регистрирую все свои сеансы терминала в iTerm2 - это все команды + вывод , со временем до нескольких секунд в моей подсказке). Формат истории по умолчанию имеет связанные с POSIX временные метки, которые более точны, чем ваши, поскольку у вас нет tzinfo. – 4ae1e1