如何从zsh历史记录中删除最后一个命令(或当前命令以获得奖励)


14

当然,有一种超级简单的智能方法可以执行此操作,但是由于zshell中的历史记录似乎是fc的别名,因此无法使用如何从历史记录中删除单行中提到的技巧

关于如何执行此操作的任何指示?我的用例是从历史记录中删除最后一个发出的命令,以使其停止自动完成(通常是在您输错了某些内容并不断显示时)。

我知道我可以通过执行以下操作获得最后发出的命令

history | tail -n 1,但历史记录-d无效,并且我找不到有关zsh的适当文档。

Answers:


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个命令。一些性感的嘘声。

按下向上箭头将直接带您到最后一个命令,也不会记住单词“ forget” :)。

更新:添加了主路径,因此它现在可以在所有目录中使用。

更新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

因此,我们可以按空格键,然后键入“ echo hi”,按Enter键,然后按向上箭头键,“ echo hi”就不在我们的历史记录中了:)。

注意别名“忘记”如何在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=' *',然后可以使用<space>启动当前命令以避免记录它。

:
 : none
fc -nl -1

:

在中zsh,您仍然可以一次调用以前的命令,但是它不会存储在历史记录中。


这没有解决问题。
克里斯·佩奇
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.