Como remover o último comando (ou comando atual para bônus) do histórico do zsh


13

Claro que existe uma maneira inteligente super simples de fazer isso, mas como o histórico no zshell parece ser alias ao fc, não há como usar os truques mencionados em Como remover uma única linha do histórico? .

Alguma dica sobre como fazer isso? Meu caso de uso seria remover o último comando emitido do histórico para que ele pare o preenchimento automático (principalmente quando você digitou algo errado e ele continua aparecendo).

Eu sei que posso obter o último comando emitido fazendo

history | tail -n 1, mas history -d não funciona e não consigo encontrar a documentação adequada para o zsh.

Respostas:


8

O Zsh não oferece uma edição de história real. O histórico do comando é basicamente somente leitura. Tudo o que você pode fazer é substituí-lo por atacado.

Para editar o histórico da linha de comando:

  1. Salve-o em um arquivo: fc -W
  2. Edite o arquivo
  3. Carregue o histórico do arquivo: fc -R

Você pode escolher o nome do arquivo definindo HISTFILE.

Código não testado:

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

Geralmente, você pode simplesmente remover a linha de ~/.zsh_history, mas se não conseguir encontrá-la, procure ~/.zshrca localização do seu arquivo de histórico.

Em seguida, use qualquer editor de texto de sua escolha para remover a (s) linha (s) ofensiva (s). Como alternativa, basta excluir o arquivo inteiro, fechar todas as instâncias zsh e iniciar uma nova. História purgada!


2

Então, sim, esse é um tópico antigo, mas nenhuma dessas perguntas respondeu para mim, então eu passei anos tentando descobrir isso também!

Aqui está minha solução com agradecimentos do @Gilles pela dica de usar 'fc -R' e 'fc -W' :).

Cole o script abaixo disso no seu arquivo .zshrc.

recarregar com a fonte .zshrc

depois digite 'esqueça' para esquecer o último comando: D. digite 'esqueça 3' para esquecer os últimos 3 comandos. Um shizz sexy.

Pressionar a seta para cima levará você direto ao último comando e também não se lembrará da palavra 'esquecer' :).

Atualizado: Adicionado caminho inicial, por isso funciona em todos os diretórios agora, lol.

Atualização 2: adicionada a capacidade de passar o número de últimos comandos que você deseja esquecer: D. Tente 'esqueça 2' para esquecer os 2 últimos comandos: 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.
}

Então, há algumas coisas acontecendo aqui. Este comando nos permitirá digitar um espaço antes de qualquer comando e não será adicionado ao histórico.

setopt histignorespace

Para podermos pressionar a barra de espaço, digite 'eco oi', pressione enter e, quando pressionamos a seta para cima, 'eco oi' não está em nossa história :).

Observe como o alias 'forget' tem um espaço antes de my_remove_last_history_entry. Isso é para que o zsh não salve nosso 'esquecer' na história.

A função explicada

O ZSH usa fc para o histórico ou algo assim, então fazemos 'fc -W' para gravar nossos comandos atuais no arquivo de histórico, e usamos 'head -n -1' para aparar o último comando do arquivo. Salvamos essa saída em um arquivo temporário e, em seguida, substituímos o arquivo de histórico original pelo temporário. E finalmente recarregue a história com fc -R.

No entanto, há um problema com a função que é corrigida com o alias.

Se executarmos a função por seu nome, ele removerá o último comando, que é a chamada para a função. É por isso que usamos o alias com uma chamada usando um espaço, para que o zsh não adicione esse nome de função ao arquivo de histórico, tornando a última entrada a que queremos: D.


e se o último comando fosse multilinhas?
avp

Isso deve ser votado como a resposta oficial. Obrigado.
gsl 16/01

1

Em zsh, defina a histignorespaceopção ( set -o histignorespace). Em bash, adicione ignorespaceou ignoreboth(algumas distribuições já fazem isso no padrão ~/.bashrc) a $HISTCONTROLou defina HISTIGNORE=' *'e, em seguida, você poderá iniciar o comando atual com um <espaço> para evitar gravá-lo.

:
 : none
fc -nl -1

:

Em zsh, você ainda pode recuperar o comando anterior uma vez, mas não está armazenado no histórico.


Isso não aborda a questão.
####
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.