如何永久更正上一個 bash 命令中的錯字?
在我的 bash 互動式 shell 中輸入命令時,我打錯字的情況並不少見。我希望能夠更正我的 bash 歷史記錄中的錯字,這樣不正確的命令就不會污染它並導致我以後不小心重新執行它。特別是,我想編輯最後一個命令。
有很多 問題詢問如何防止意外編輯 bash 歷史記錄。 我想要相反:我想明確地編輯歷史。
根據參考問題的一些解釋,我嘗試這樣做:
$ echo foo
按
Up
,將其更改為:$ echo foobar
按
Down
,但什麼也沒做,如果我再按Enter
,它將執行修改後的命令並保留兩者echo foo echo foobar
在我的歷史中。
我知道我可以使用 手動刪除歷史條目
history -d
,但我還沒有設計出一種方便使用它的好方法。我不想製作一個 shell 函式來無條件地刪除最後一個歷史條目,因為我仍然希望能夠用來Up
載入最後一個條目以便我可以更正它。我可以進行更正,然後刪除倒數第二個歷史條目,但這感覺很笨拙,而且對於長時間執行的命令來說尤其煩人,因為我要麼需要記住稍後執行額外的步驟,要麼需要暫時掛起它,執行這些步驟,然後繼續。我想要的是:
- 理想情況下,我希望能夠按
Up
,對我以前的命令進行更正,然後按一些特殊的鍵綁定或向命令行添加一些魔術標記,以使其在執行時替換歷史記錄條目。- 還可以按其他鍵序列從歷史記錄中檢索和編輯命令(類似於 Ctrl+R),該命令在執行時會覆蓋歷史記錄條目。
- 刪除倒數第二個歷史條目的健壯shell 函式是可以容忍的,但並不理想。
我想其他人肯定也會打錯字,當這樣的命令污染他們的歷史時,他們也會同樣生氣。其他人做什麼?
HSTR看起來很吸引人,但結果對我來說有點太重了。
相反,我編寫了自己的 bash 函式:
# Removes the last command from the history that matches the given search # string and re-executes it using the given replacement string. # # Usage: # historysub SEARCH [REPLACEMENT] # historysub -d SEARCH # # REPLACEMENT may be omitted to remove SEARCH from the executed command. # # -d removes the last command matching SEARCH from the history without # executing a new command. historysub() { local delete=0 local usage=0 local OPTIND=1 while getopts ":hd" option; do case "${option}" in d) delete=1 ;; h) usage=1 ;; ?) usage=2 ;; esac done shift $((OPTIND - 1)) local search="${1-}" local replacement="${2-}" usage_text= usage_text+="Usage: ${FUNCNAME[0]} SEARCH [REPLACEMENT]\n" usage_text+=" ${FUNCNAME[0]} -d SEARCH\n" if (( usage )); then echo -e "${usage_text}" return $(( usage - 1 )) fi if [[ -z "${search}" ]]; then echo -e "${usage_text}" >&2 return 1 fi # RE to parse the `history` output. local hist_re='^[ \t]*([0-9]+)[ \t]+(.+)$' local hist_full hist_full=$(HISTTIMEFORMAT="" history) # We don't want the search string to accidentally match against history # numbers, so split the `history` output so that we can search against just # the commands. local hist_nums hist_cmds hist_nums=$(sed -E "s/${hist_re}/\1/" <<< "${hist_full}") hist_cmds=$(sed -E "s/${hist_re}/\2/" <<< "${hist_full}") # Find the last matching history entry (excluding ourself). local matches last_match matches=$(grep -nF -- "${search}" <<< "${hist_cmds}") last_match=$(grep -vF -- "${FUNCNAME[0]}" <<< "${matches}" | tail -n 1) if [[ -z "${last_match}" ]]; then echo "${FUNCNAME[0]}: \"${search}\" not found." >&2 return 1 fi # RE to parse the `grep -n` output. local line_re='^([0-9]+):[ \t]*(.+)$' # Note that the line number and the history number might not be the same, so # we need to retrieve the original history number. local line_num hist_cmd hist_num line_num=$(sed -E "s/${line_re}/\1/" <<< "${last_match}") hist_cmd=$(sed -E "s/${line_re}/\2/" <<< "${last_match}") hist_num=$(tail -n +${line_num} <<< "${hist_nums}" | head -n 1) history -d "${hist_num}" if (( delete )); then echo "Removed: ${hist_cmd}" return 0 fi local cmd="${hist_cmd/${search}/${replacement}}" echo "${cmd}" # Add the new command to the history. history -s -- "${cmd}" eval -- "${cmd}" }
所以現在我可以執行
historysub TYPO CORRECTION
以重新執行帶有更正的命令。它不如能夠互動式地編輯舊命令,但我認為它應該足以滿足我的需求。
選項 #1 - 手動
我只需
~/.bash_history
在編輯器中打開文件,vim
然後對該文件進行所需的任何更改並保存。$ vim ~/.bash_history
在編輯它之前,確保你目前的終端歷史也被送出到這個文件:
$ history -a
請記住,您的歷史文件位於此環境變數指向的任何位置:
$ echo $HISTFILE /Users/user1/.bash_history
選項 #2 - HSTR
有一個名為 HSTR 的 CLI 工具,您可以使用它以
~/.bash_history
更系統的方式管理您的文件。HSTR的主要網站是影片和使用它的詳細資訊。它還提到了這個簡介:
HSTR 還可以管理您的命令歷史記錄(例如,您可以刪除過時或包含敏感資訊的命令)或為您喜歡的命令添加書籤。
有關更多資訊,請參閱完整文件:HSTR DOCUMENTATION。
參考