Come rimuovere l'ultimo comando (o il comando corrente per il bonus) dalla cronologia di zsh


13

Sicuramente esiste un modo molto semplice per farlo, ma poiché la storia in zshell sembra essere aliasata in fc, non c'è modo di usare i trucchi menzionati in Come rimuovere una singola linea dalla storia? .

Qualche suggerimento su come farlo? Il mio caso d'uso sarebbe quello di rimuovere l'ultimo comando emesso dalla cronologia in modo da interrompere il completamento automatico (soprattutto quando hai sbagliato a digitare qualcosa e continua a essere visualizzato).

So di poter ottenere l'ultimo comando emesso facendo

history | tail -n 1, ma la storia -d non funziona e non riesco a trovare la documentazione corretta per zsh.

Risposte:


8

Zsh non offre una funzione di edizione storica reale. La cronologia dei comandi è sostanzialmente di sola lettura. Tutto quello che puoi fare è sostituirlo all'ingrosso.

Per modificare la cronologia della riga di comando:

  1. Salvalo in un file: fc -W
  2. Modifica il file
  3. Carica la cronologia dal file: fc -R

Puoi scegliere il nome del file impostando HISTFILE.

Codice non testato:

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

Di solito puoi semplicemente rimuovere la linea da ~/.zsh_history, ma se non riesci a trovarla cerca ~/.zshrcla posizione del tuo file di cronologia.

Quindi utilizza qualsiasi editor di testo a tua scelta per rimuovere le righe offensive. In alternativa, basta eliminare l'intero file e chiudere tutte le istanze zsh e avviarne uno nuovo. La storia è stata purificata!


2

Quindi sì, questo è un vecchio argomento, ma nessuna di queste domande mi ha risposto, quindi ho passato anni a cercare di capirlo!

Ecco la mia soluzione con ringraziamenti da @Gilles per il suggerimento di usare 'fc -R' e 'fc -W' :).

Incolla lo script qui sotto nel tuo file .zshrc.

ricaricare con il sorgente .zshrc

quindi digitare 'dimenticare' per dimenticare l'ultimo comando: D. digitare 'dimenticare 3' per dimenticare gli ultimi 3 comandi. Qualche shizz sexy.

Premendo la freccia su si accederà direttamente all'ultimo comando e non si ricorderà nemmeno la parola 'dimenticare' :).

Aggiornato: aggiunto il percorso principale, quindi funziona in tutte le directory ora lol.

Aggiornamento 2: aggiunta la possibilità di passare il numero degli ultimi comandi che si desidera dimenticare: D. Prova a "dimenticare 2" per dimenticare gli ultimi 2 comandi: 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.
}

Quindi ci sono alcune cose che stanno succedendo qui. Questo comando ci consentirà di digitare uno spazio prima di qualsiasi comando e non verrà aggiunto alla cronologia.

setopt histignorespace

Quindi possiamo premere la barra spaziatrice e digitare 'echo hi', premere invio e quando premiamo la freccia su, 'echo hi' non è nella nostra storia :).

Nota come l'alias 'dimenticare' ha uno spazio prima di my_remove_last_history_entry. Questo in modo che zsh non salvi il nostro "dimenticare" nella storia.

La funzione ha spiegato

ZSH usa fc per la cronologia o qualcosa del genere, quindi facciamo 'fc -W' per scrivere i nostri comandi correnti nel file della cronologia, li usiamo 'head -n -1' per tagliare l'ultimo comando dal file. Salviamo quell'output in un file temporaneo e quindi sostituiamo il file cronologico originale con quello temporaneo. E infine ricaricare la storia con fc -R.

Esiste tuttavia un problema con la funzione che è stata risolta con l'alias.

Se eseguiamo la funzione con il suo nome, rimuoverà l'ultimo comando, che è la chiamata alla funzione. Questo è il motivo per cui usiamo l'alias con una chiamata usando uno spazio, in modo che zsh non aggiunga questo nome di funzione al file della cronologia, rendendo l'ultima voce quella che vogliamo: D.


e se l'ultimo comando fosse multilinea?
avp

Questa dovrebbe essere votata come risposta ufficiale. Grazie.
GSL

1

In zsh, imposta l' histignorespaceopzione ( set -o histignorespace). E in bash, aggiungi ignorespaceo ignoreboth(alcune distribuzioni lo fanno già nel default ~/.bashrc) a $HISTCONTROLo imposta HISTIGNORE=' *', e quindi puoi avviare il comando corrente con uno <spazio> per evitare di registrarlo.

:
 : none
fc -nl -1

:

In zsh, puoi ancora richiamare quel comando precedente una volta, ma non è memorizzato nella cronologia.


Questo non affronta la domanda.
Chris Page,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.