Cara menghapus perintah terakhir (atau perintah saat ini untuk bonus) dari zsh history


13

Tentu ada cara pintar super sederhana untuk melakukan ini, tetapi karena sejarah di zshell tampaknya alias fc, tidak ada cara untuk menggunakan trik yang disebutkan dalam Cara menghapus satu baris dari sejarah? .

Adakah petunjuk tentang cara melakukan ini? Kasus penggunaan saya adalah menghapus perintah yang dikeluarkan terakhir dari riwayat sehingga berhenti melakukan pelengkapan otomatis (sebagian besar ketika Anda salah mengetik sesuatu dan terus muncul).

Saya tahu saya bisa mendapatkan perintah yang dikeluarkan terakhir dengan melakukan

history | tail -n 1, tetapi history -d tidak berfungsi dan saya tidak dapat menemukan dokumentasi yang tepat untuk zsh.

Jawaban:


8

Zsh tidak menawarkan fasilitas edisi sejarah nyata. Sejarah perintah pada dasarnya hanya baca. Yang bisa Anda lakukan hanyalah menggantinya secara grosir.

Untuk mengedit riwayat baris perintah:

  1. Simpan ke file: fc -W
  2. Edit file
  3. Muat riwayat dari file: fc -R

Anda dapat memilih nama file dengan mengatur HISTFILE.

Kode yang belum diuji:

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

Biasanya Anda hanya dapat menghapus baris dari ~/.zsh_history, tetapi jika Anda tidak dapat menemukannya mencari ~/.zshrclokasi file riwayat Anda.

Kemudian gunakan editor teks pilihan Anda untuk menghapus baris yang menyinggung. Atau, hapus saja seluruh file dan tutup semua instance zsh dan mulai yang baru. Sejarah dibersihkan!


2

Jadi ya, ini adalah topik lama, tetapi tidak satu pun dari pertanyaan ini yang menjawabnya untuk saya, jadi saya menghabiskan waktu lama untuk mencari tahu juga!

Inilah solusi saya dengan terima kasih dari @Gilles untuk petunjuk menggunakan 'fc -R' dan 'fc -W' :).

Rekatkan skrip di bawah ini ke dalam file .zshrc Anda.

memuat ulang dengan sumber .zshrc

lalu ketik 'lupa' untuk melupakan perintah terakhir: D. ketik 'forget 3' untuk melupakan 3 perintah terakhir. Beberapa shizz seksi.

Menekan panah ke atas akan membawa Anda langsung ke perintah terakhir dan tidak akan mengingat kata 'lupa' juga :).

Diperbarui: Jalur rumah ditambahkan, sehingga berfungsi di semua direktori sekarang lol.

Pembaruan 2: Menambahkan kemampuan untuk meneruskan jumlah perintah terakhir yang ingin Anda lupakan: D. Coba 'lupa 2' untuk melupakan 2 perintah terakhir: 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.
}

Jadi ada beberapa hal yang terjadi di sini. Perintah ini akan memungkinkan kita mengetik spasi sebelum perintah apa pun, dan itu tidak akan ditambahkan ke riwayat.

setopt histignorespace

Jadi kita bisa menekan spasi, dan ketik 'echo hi', tekan enter dan ketika kita menekan panah ke atas, 'echo hi' tidak ada dalam sejarah kita :).

Perhatikan bagaimana alias 'lupa' memiliki spasi sebelum my_remove_last_history_entry. Ini agar zsh tidak menyimpan 'lupa' kami ke riwayat.

Fungsi itu menjelaskan

ZSH menggunakan fc untuk histori atau sesuatu, jadi kita melakukan 'fc -W' untuk menulis perintah kita saat ini ke file history, mereka kita gunakan 'head -n -1' untuk memangkas perintah terakhir dari file. Kami menyimpan output itu ke file sementara dan kemudian mengganti file histori asli dengan temp. Dan akhirnya memuat ulang sejarah dengan fc -R.

Namun ada masalah dengan fungsi yang diperbaiki dengan alias.

Jika kita menjalankan fungsi dengan nama itu, itu akan menghapus perintah terakhir, yang merupakan panggilan ke fungsi. Inilah sebabnya kami menggunakan alias dengan panggilan ke sana menggunakan spasi, sehingga zsh tidak menambahkan nama fungsi ini ke file histori, menjadikan entri terakhir yang kami inginkan: D.


bagaimana jika perintah terakhir adalah multi-line?
avp

Ini harus dipilih sebagai jawaban resmi. Terima kasih.
gsl

1

Di zsh, atur histignorespaceopsi ( set -o histignorespace). Dan di bash, tambahkan ignorespaceatau ignoreboth(beberapa distribusi sudah melakukannya di default ~/.bashrc) ke $HISTCONTROLatau set HISTIGNORE=' *', dan kemudian Anda dapat memulai perintah saat ini dengan <spasi> untuk menghindari merekamnya.

:
 : none
fc -nl -1

:

Di zsh, Anda masih dapat mengingat perintah sebelumnya sekali, tetapi itu tidak disimpan dalam sejarah.


Ini tidak menjawab pertanyaan.
Chris Halaman
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.