Как удалить последнюю команду (или текущую команду для бонуса) из истории Zsh

13

Конечно, есть очень простой умный способ сделать это, но, поскольку история в zshell, кажется, имеет псевдоним fc, нет способа использовать приемы, упомянутые в разделе Как удалить одну строку из истории? ,

Любые указатели о том, как это сделать? Мой вариант использования будет состоять в том, чтобы удалить последнюю введенную команду из истории, чтобы она прекратила автозаполнение (в основном, когда вы что-то опечатали и продолжают появляться).

Я знаю, что могу получить последнюю команду, выполнив

history | tail -n 1, но история -d не работает, и я не могу найти соответствующую документацию для zsh.

Алекс С
источник

Ответы:

8

Zsh не предлагает возможности для создания реальной истории. История команд в основном только для чтения. Все, что вы можете сделать, это заменить его оптом.

Чтобы редактировать историю командной строки:

  1. Сохраните его в файл: fc -W
  2. Редактировать файл
  3. Загрузите историю из файла: fc -R

Вы можете выбрать имя файла, установив HISTFILE.

Непроверенный код:

remove_last_history_entry () {
  setopt local_options extended_history no_hist_save_no_dups err_return

  local HISTFILE=~/.zsh_history_tmp_$$ SAVEHIST=$HISTSIZE
  fc -W
  ed -s $HISTFILE <<EOF >/dev/null
d
w
q
EOF
  fc -R
}
Жиль "ТАК - перестань быть злым"
источник
6

Обычно вы можете просто удалить строку ~/.zsh_history, но если вы не можете найти ее, найдите ~/.zshrcместоположение файла истории.

Затем используйте любой текстовый редактор по вашему выбору, чтобы удалить оскорбительные строки. Либо просто удалите весь файл, закройте все экземпляры zsh и запустите новый. История очищена!

kcrk
источник
2

Так что да, это старая тема, но ни один из этих вопросов не ответил на это для меня, поэтому я просто потратил целую вечность, пытаясь понять это тоже!

Вот Мое решение с благодарностью от @Gilles за подсказку об использовании 'fc -R' и 'fc -W' :).

Вставьте скрипт ниже этого в ваш файл .zshrc.

перезагрузить с источником .zshrc

затем наберите «забыть», чтобы забыть последнюю команду: D. Наберите «забыть 3», чтобы забыть последние 3 команды. Некоторая сексуальная пизда.

Нажатие стрелки вверх приведет вас прямо к последней команде и не запомнит слово «забудь» :).

Обновлено: добавлен домашний путь, теперь он работает во всех каталогах.

Обновление 2: добавлена ​​возможность передавать количество последних команд, которые вы хотите забыть: D. Попробуйте «забыть 2», чтобы забыть последние 2 команды: D.

# Put a space at the start of a command to make sure it doesn't get added to the history.
setopt histignorespace

alias forget=' my_remove_last_history_entry' # Added a space in 'my_remove_last_history_entry' so that zsh forgets the 'forget' command :).

# ZSH's history is different from bash,
# so here's my fucntion to remove
# the last item from history.
my_remove_last_history_entry() {
    # This sub-function checks if the argument passed is a number.
    # Thanks to @yabt on stackoverflow for this :).
    is_int() ( return $(test "$@" -eq "$@" > /dev/null 2>&1); )

    # Set history file's location
    history_file="${HOME}/.zsh_history"
    history_temp_file="${history_file}.tmp"
    line_cout=$(wc -l $history_file)

    # Check if the user passed a number,
    # so we can delete x lines from history.
    lines_to_remove=1
    if [ $# -eq 0 ]; then
        # No arguments supplied, so set to one.
        lines_to_remove=1
    else
        # An argument passed. Check if it's a number.
        if $(is_int "${1}"); then
            lines_to_remove="$1"
        else
            echo "Unknown argument passed. Exiting..."
            return
        fi
    fi

    # Make the number negative, since head -n needs to be negative.
    lines_to_remove="-${lines_to_remove}"

    fc -W # write current shell's history to the history file.

    # Get the files contents minus the last entry(head -n -1 does that)
    #cat $history_file | head -n -1 &> $history_temp_file
    cat $history_file | head -n "${lines_to_remove}" &> $history_temp_file
    mv "$history_temp_file" "$history_file"

    fc -R # read history file.
}

Так что здесь происходит несколько вещей. Эта команда позволит нам ввести пробел перед любой командой, и она не будет добавлена ​​в историю.

setopt histignorespace

Таким образом, мы можем нажать клавишу пробела и набрать «echo hi», нажать Enter, а когда мы нажимаем стрелку вверх, «echo hi» не в нашей истории :).

Обратите внимание, что псевдоним «забыть» имеет пробел перед my_remove_last_history_entry. Это так, что zsh не сохраняет наше «забытие» в истории.

Функция объяснила

ZSH использует fc для истории или чего-то еще, поэтому мы делаем 'fc -W', чтобы записать наши текущие команды в файл истории, их мы используем 'head -n -1', чтобы обрезать последнюю команду из файла. Мы сохраняем этот вывод во временный файл, а затем заменяем исходный файл истории временным. И, наконец, перезагрузите историю с помощью fc -R.

Однако есть проблема с функцией, которая исправлена ​​с помощью псевдонима.

Если мы запустим функцию по ее имени, она удалит последнюю команду, которая является вызовом функции. Вот почему мы используем псевдоним при обращении к нему, используя пробел, так что zsh не добавляет это имя функции в файл истории, делая последнюю запись той, которую мы хотим: D.

pandagoespoop
источник
что если последняя команда была многострочной?
AVP
Это следует признать официальным ответом. Благодарю.
GSL
1

В zsh, установите histignorespaceопцию ( set -o histignorespace). И в bash, добавьте ignorespaceили ignoreboth(некоторые дистрибутивы уже делают это по умолчанию ~/.bashrc) в $HISTCONTROLили установите HISTIGNORE=' *', и затем вы можете запустить текущую команду с <пробелом>, чтобы избежать ее записи.

:
 : none
fc -nl -1

:

В zsh, вы все еще можете вспомнить эту предыдущую команду один раз, но она не сохраняется в истории.

mikeserv
источник
Это не решает вопрос.
Крис Пейдж