zsh履歴から最後のコマンド(またはボーナスの現在のコマンド)を削除する方法


13

確かにこれを行うには非常にシンプルなスマートな方法がありますが、zshellの履歴はfcにエイリアスされているように見えるため、「履歴から1行を削除する方法」に記載されているトリックを使用する方法はありませんか?

これを行う方法に関する指針はありますか?私の使用例は、最後に発行されたコマンドを履歴から削除して、オートコンプリートを停止することです(ほとんどの場合、タイプミスして表示され続ける場合)。

私は次のようにして最後に発行されたコマンドを取得できます

history | tail -n 1、しかし、history -dは機能せず、zshの適切なドキュメントが見つかりません。

回答:


8

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

ええ、これは古いトピックですが、これらの質問のどれも私に答えることができなかったので、これを理解しようと何年も費やしました!

これは、 'fc -R'と 'fc -W'を使用するヒントについて@Gilles感謝する私の解決策です。

この下のスクリプトを.zshrcファイルに貼り付けます。

ソース.zshrcでリロード

次に「forget」と入力して、最後のコマンドを忘れます:D。最後の3つのコマンドを忘れるには、「forget 3」と入力します。セクシーなシズ。

上矢印を押すと、最後のコマンドに直接移動し、「忘れる」という単語も覚えていません。

更新:ホームパスが追加されたため、すべてのディレクトリで機能するようになりました(笑)。

更新2:忘れたい最後のコマンドの数を渡す機能が追加されました:D。最後の2つのコマンドを忘れるには、 'forget 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」は履歴にありません。

エイリアス「forget」がmy_remove_last_history_entryの前にスペースがあることに注意してください。これは、zshが「忘れる」ことを履歴に保存しないようにするためです。

機能説明

ZSHは履歴などにfcを使用するため、「fc -W」を使用して現在のコマンドを履歴ファイルに書き込み、「head -n -1」を使用してファイルから最後のコマンドを削除します。その出力を一時ファイルに保存してから、元の履歴ファイルを一時ファイルに置き換えます。そして最後にfc -Rで履歴を再読み込みします。

ただし、エイリアスで修正された関数には問題があります。

関数をその名前で実行すると、最後のコマンド(関数の呼び出し)が削除されます。これが、スペースを使用してエイリアスを呼び出し、エイリアスを使用する理由です。これにより、zshはこの関数名を履歴ファイルに追加せず、最後のエントリを目的のエントリにします。


最後のコマンドが複数行の場合はどうなりますか?
avp

これは公式の回答として投票されるべきです。ありがとう。
gsl

1

zshhistignorespaceオプション(set -o histignorespace)を設定します。でbashignorespaceまたはignoreboth(一部のディストリビューションでは既にデフォルトでそれが行われている~/.bashrc)を$HISTCONTROLまたはに追加してHISTIGNORE=' *'から、現在のコマンドを<スペース>で開始して、それを記録しないようにすることができます。

:
 : none
fc -nl -1

:

ではzsh、以前のコマンドを一度呼び出すことができますが、履歴には保存されません。


これは問題に対処していません。
Chris Page
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.