Як видалити останню команду (або поточну команду для бонусу) з історії zsh


14

Звичайно, існує надзвичайно простий розумний спосіб зробити це, але оскільки історія в zshell, здається, псевдонім fc, немає способу використовувати хитрощі, згадані в розділі Як видалити єдиний рядок з історії? .

Будь-які вказівки, як це зробити? Моїм випадком використання буде видалення останньої виданої команди з історії, щоб вона припиняла автоматичне завершення (переважно, коли ви щось помилково ввели, і вона постійно відображається).

Я знаю, що я можу отримати останню видану команду, виконавши

history | tail -n 1, але історія -d не працює, і я не можу знайти належну документацію для zsh.

Відповіді:


9

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 та запустіть новий. Історія очищена!


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

Таким чином, ми можемо натиснути пробіл і набрати "ехо привіт", натиснути клавішу Enter, і коли ми натискаємо стрілку вгору, "ехо привіт" немає в нашій історії :).

Зверніть увагу, як у псевдоніму "забути" пробіл перед my_remove_last_history_entry. Це так, що zsh не зберігає наше «забуття» в історії.

Функція пояснена

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

Однак існує проблема з функцією, яка фіксується псевдонімом.

Якщо ми запустимо функцію за своїм ім'ям, вона видалить останню команду, яка є викликом до функції. Ось чому ми використовуємо псевдонім з викликом до нього, використовуючи пробіл, щоб zsh не додав цю назву функції до файла історії, зробивши останній запис таким, який ми хочемо: D.


що робити, якщо остання команда була багаторядковою?
AVP

Це має бути проголосовано як офіційна відповідь. Спасибі.
gsl

1

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

:
 : none
fc -nl -1

:

В zsh, ви можете згадати , що попередню команду один раз, але це не зберігається в історії.


Це не стосується питання.
Chris Page
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.