Jak usunąć ostatnie polecenie (lub bieżące polecenie za bonus) z historii zsh

14

Pewnie, że jest to bardzo prosty, inteligentny sposób, aby to zrobić, ale ponieważ historia w Zshell wydaje się być aliasowana do fc, nie ma sposobu na użycie sztuczek wymienionych w Jak usunąć pojedynczy wiersz z historii? .

Wszelkie wskazówki, jak to zrobić? Moim przypadkiem użycia byłoby usunięcie ostatniego wydanego polecenia z historii, aby zatrzymać automatyczne uzupełnianie (głównie, gdy coś źle wpisałeś i ciągle się wyświetla).

Wiem, że mogę uzyskać ostatnio wydane polecenie, wykonując polecenie

history | tail -n 1, ale historia -d nie działa i nie mogę znaleźć odpowiedniej dokumentacji dla zsh.

Alex S.
źródło

Odpowiedzi:

9

Zsh nie oferuje funkcji edycji historii. Historia poleceń jest w zasadzie tylko do odczytu. Wszystko, co możesz zrobić, to wymienić go hurtowo.

Aby edytować historię wiersza poleceń:

  1. Zapisz go w pliku: fc -W
  2. Edytuj plik
  3. Załaduj historię z pliku: fc -R

Możesz wybrać nazwę pliku poprzez ustawienie HISTFILE.

Nieprzetestowany kod:

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
}
Gilles „SO- przestań być zły”
źródło
6

Zwykle możesz po prostu usunąć linię ~/.zsh_history, ale jeśli nie możesz jej znaleźć, poszukaj ~/.zshrclokalizacji pliku historii.

Następnie użyj dowolnego edytora tekstu, aby usunąć obrażające się linie. Alternatywnie, po prostu usuń cały plik i zamknij wszystkie instancje zsh i uruchom nowy. Historia oczyszczona!

kcrk
źródło
2

Tak, to jest stary temat, ale żadne z tych pytań nie udzieliło mi odpowiedzi, więc spędziłem całe wieki próbując to rozgryźć!

Oto Moje rozwiązanie z podziękowaniami od @Gilles za podpowiedź użycia „fc -R” i „fc -W” :).

Wklej poniższy skrypt do pliku .zshrc.

przeładuj ze źródłowym .zshrc

następnie wpisz „zapomnij”, aby zapomnieć ostatnie polecenie: D. wpisz „zapomnij 3”, aby zapomnieć 3 ostatnie polecenia. Niektóre seksowne shizz.

Naciśnięcie strzałki w górę przeniesie Cię bezpośrednio do ostatniego polecenia i nie zapamiętasz też słowa „zapomnij” :).

Zaktualizowano: Dodano ścieżkę główną, więc działa teraz we wszystkich katalogach lol.

Aktualizacja 2: Dodano możliwość przekazywania liczby ostatnich poleceń, które chcesz zapomnieć: D. Spróbuj „zapomnieć 2”, aby zapomnieć 2 ostatnie polecenia: 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.
}

A więc dzieje się tutaj kilka rzeczy. To polecenie pozwoli nam wpisać spację przed dowolnym poleceniem i nie zostanie dodane do historii.

setopt histignorespace

Możemy więc nacisnąć spację i wpisać „echo hi”, nacisnąć enter, a kiedy naciskamy strzałkę w górę, „echo hi” nie jest w naszej historii :).

Zauważ, że alias „zapomnij” ma spację przed my_remove_last_history_entry. Dzieje się tak, aby zsh nie zapisał naszego „zapomnienia” w historii.

Funkcja wyjaśniona

ZSH używa fc do historii lub czegoś takiego, więc robimy „fc -W”, aby zapisać nasze bieżące polecenia do pliku historii, używamy „head -n -1”, aby przyciąć ostatnie polecenie z pliku. Zapisujemy ten wynik w pliku tymczasowym, a następnie zastępujemy oryginalny plik historii plikiem tymczasowym. I w końcu przeładuj historię fc -R.

Występuje jednak problem z funkcją, która jest naprawiona przez alias.

Jeśli uruchomimy funkcję po nazwie, usunie ona ostatnie polecenie, które jest wywołaniem funkcji. Dlatego używamy aliasu z wywołaniem do niego za pomocą spacji, aby zsh nie dodawał tej nazwy funkcji do pliku historii, czyniąc ostatni wpis tym, którego chcemy: D.

pandagoespoop
źródło
co jeśli ostatnie polecenie było wielowierszowe?
avp
Należy to przegłosować jako oficjalną odpowiedź. Dzięki.
gsl
1

W zshustaw histignorespaceopcję ( set -o histignorespace). I w bash, dodaj ignorespacelub ignoreboth(niektóre dystrybucje już to robią domyślnie ~/.bashrc) do $HISTCONTROLlub ustaw HISTIGNORE=' *', a następnie możesz uruchomić bieżące polecenie za pomocą <spacji>, aby uniknąć jego nagrania.

:
 : none
fc -nl -1

:

W zshnadal możesz raz przywołać poprzednie polecenie, ale nie jest ono przechowywane w historii.

mikeserv
źródło
To nie dotyczy pytania.
Chris Page