Comment supprimer la dernière commande (ou la commande actuelle pour le bonus) de l'historique zsh

14

Bien sûr, il existe un moyen très simple et intelligent de le faire, mais comme l'historique dans zshell semble être alias de fc, il n'y a aucun moyen d'utiliser les astuces mentionnées dans Comment supprimer une seule ligne de l'historique? .

Des conseils sur la façon de procéder? Mon cas d'utilisation serait de supprimer la dernière commande émise de l'historique pour qu'elle arrête la saisie semi-automatique (surtout lorsque vous avez mal tapé quelque chose et qu'elle continue de s'afficher).

Je sais que je peux obtenir la dernière commande émise en faisant

history | tail -n 1, mais history -d ne fonctionne pas et je ne trouve pas la documentation appropriée pour zsh.

Alex S
la source

Réponses:

9

Zsh ne propose pas de véritable installation d'édition d'histoire. L'historique des commandes est essentiellement en lecture seule. Tout ce que vous pouvez faire est de le remplacer en gros.

Pour modifier l'historique de la ligne de commande:

  1. Enregistrez-le dans un fichier: fc -W
  2. Modifier le fichier
  3. Chargez l'historique à partir du fichier: fc -R

Vous pouvez choisir le nom de fichier en définissant HISTFILE.

Code non testé:

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- arrête d'être méchant'
la source
6

Habituellement, vous pouvez simplement supprimer la ligne ~/.zsh_history, mais si vous ne la trouvez pas, recherchez ~/.zshrcl'emplacement de votre fichier d'historique.

Utilisez ensuite n'importe quel éditeur de texte de votre choix pour supprimer la ou les lignes incriminées. Sinon, supprimez simplement le fichier entier et fermez toutes les instances zsh et commencez-en un nouveau. Histoire purgée!

kcrk
la source
2

Alors oui, c'est un vieux sujet, mais aucune de ces questions n'y a répondu pour moi donc j'ai passé des siècles à essayer de comprendre ça aussi!

Voici ma solution avec les remerciements de @Gilles pour le conseil d'utiliser 'fc -R' et 'fc -W' :).

Collez le script ci-dessous dans votre fichier .zshrc.

recharger avec la source .zshrc

puis tapez «oublier» pour oublier la dernière commande: D. tapez 'oublier 3' pour oublier les 3 dernières commandes. Du shizz sexy.

Appuyer sur la flèche vers le haut vous amènera directement à la dernière commande et ne se souviendra pas non plus du mot «oublier» :).

Mise à jour: chemin d'accueil ajouté, donc cela fonctionne dans tous les répertoires maintenant lol.

Mise à jour 2: Ajout de la possibilité de passer le nombre de dernières commandes que vous souhaitez oublier: D. Essayez 'oublier 2' pour oublier les 2 dernières commandes: 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.
}

Il se passe donc quelques choses ici. Cette commande nous permettra de taper un espace avant toute commande, et il ne sera pas ajouté à l'historique.

setopt histignorespace

Nous pouvons donc appuyer sur la barre d'espace et taper «écho salut», appuyez sur entrée et lorsque nous appuyons sur la flèche vers le haut, «écho salut» n'est pas dans notre histoire :).

Remarquez comment l'alias «oublier» a un espace avant my_remove_last_history_entry. C'est ainsi que zsh ne sauve pas notre «oublier» à l'histoire.

La fonction expliquée

ZSH utilise fc pour l'historique ou quelque chose, donc nous faisons 'fc -W' pour écrire nos commandes actuelles dans le fichier historique, nous utilisons 'head -n -1' pour couper la dernière commande du fichier. Nous enregistrons cette sortie dans un fichier temporaire, puis remplaçons le fichier historique d'origine par celui temporaire. Et enfin, rechargez l'historique avec fc -R.

Il y a cependant un problème avec la fonction qui est corrigée avec l'alias.

Si nous exécutons la fonction par son nom, elle supprimera la dernière commande, qui est l'appel à la fonction. C'est pourquoi nous utilisons l'alias avec un appel à celui-ci en utilisant un espace, afin que zsh n'ajoute pas ce nom de fonction au fichier historique, faisant de la dernière entrée celle que nous voulons: D.

pandagoespoop
la source
et si la dernière commande était multi-ligne?
avp
Cela devrait être voté comme réponse officielle. Merci.
gsl
1

Dans zsh, définissez l' histignorespaceoption ( set -o histignorespace). Et dans bash, ajoutez ignorespaceou ignoreboth(certaines distributions le font déjà par défaut ~/.bashrc) à $HISTCONTROLou définissez HISTIGNORE=' *', puis vous pouvez démarrer la commande actuelle avec un <espace> pour éviter de l'enregistrer.

:
 : none
fc -nl -1

:

Dans zsh, vous pouvez toujours rappeler cette commande précédente une fois, mais elle n'est pas stockée dans l'historique.

mikeserv
la source
Cela ne règle pas la question.
Chris Page