Bash

在 bash 中替代 Ctrl-R 反向搜尋

  • December 7, 2021

我很高興並且非常喜歡 bash shell 的Ctrl向後R搜尋功能。我的一些同事不喜歡它,因為它有時會令人困惑。我理解他們。如果您輸入了錯誤的字元,則歷史中的目前位置是過去的某個位置,您將找不到最近的匹配項。

在 shell 歷史中向後搜尋是否有更使用者友好的替代方案?

我想堅持使用 bash。建議替代外殼不是這個問題的答案。

這裡解釋了“失去位置”的問題:Reset bash history search position。這些解決方案有效。這是正確的。但是根據我的觀點,那裡的解決方案並不容易且使用者友好。這些解決方案並不簡單直接。這些都是過去的解決方案。在過去,人類需要學習電腦想要輸入的方式。但是今天,這些工具應該以一種對使用者來說很容易的方式接受輸入。

也許有人知道像 PyCharm 這樣的 jetbrains IDE。如果您搜尋“foobar”,您甚至會得到包含“foo_bar”的行。太好了,這就是 unix :-)

我正在使用模糊查找程序FZF。我編寫了自己的鍵綁定和 shell 腳本,以利用FZF作為我選擇的工具來反向搜尋互動式Bash shell 的歷史。隨意從我的Config GitHub 儲存庫中複製和粘貼程式碼。

~/.bashrc 配置文件

# Test if fuzzy finder program _Fzf_ is installed.
#
if type -p fzf &> /dev/null; then

 # Test if _Fzf_ specific _Readline_ file is readable.
 #
 if [[ -f ~/.inputrc.fzf && -r ~/.inputrc.fzf ]]; then

   # Make _Fzf_ available through _Readline_ key bindings.
   #
   bind -f ~/.inputrc.fzf
 fi
fi

~/.inputrc.fzf 配置文件##

$if mode=vi

 # Key bindings for _Vi_ _Insert_ mode
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 set keymap vi-insert

 "\C-x\C-a": vi-movement-mode
 "\C-x\C-e": shell-expand-line
 "\C-x\C-r": redraw-current-line
 "\C-x^": history-expand-line
 "\C-r": "\C-x\C-addi$(HISTTIMEFORMAT= history | fzf-history)\C-x\C-e\C-x\C-r\C-x^\C-x\C-a$a"

 # Key bindings for _Vi_ _Command_ mode
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 set keymap vi-command

 "\C-r": "i\C-r"
 "\ec": "i\ec"

$endif

fzf-history 可執行 Bash 腳本

#!/usr/bin/env bash
#
# Retrieve command from history with fuzzy finder
# ===============================================
# Tim Friske <me@tifr.de>
#
# See also:
#   * man:bash[1]
#   * man:fzf[1]
#   * man:cat[1]

shopt -os nounset pipefail errexit errtrace
shopt -s extglob globstar

function print_help {
 1>&2 cat \
<<'HELP'
usage:
 HISTTIMEFORMAT= history | fzf-history
HELP
}

function fzf_history {
 if [[ -t 0 ]]; then
   print_help
   exit
 fi

 local fzf_options=()
 fzf_options+=(${FZF_DEFAULT_OPTS:-})
 fzf_options+=('--tac' '-n2..,..' '--tiebreak=index')
 fzf_options+=(${FZF_HISTORY_FZF_OPTS:-})
 fzf_options+=('--print0')

 local cmd='' cmds=()
 while read -r -d '' cmd; do
   cmds+=("${cmd/#+([[:digit:]])+([[:space:]])/}")
 done < <(fzf "${fzf_options[@]}")
 if [[ "${#cmds[*]}" -gt 0 ]]; then
   (IFS=';'; printf '%s\n' "${cmds[*]}")
 fi
}

fzf_history "$@"

key-bindings.bash 源 Bash 腳本

取自FZF 的 Bash 鍵綁定文件並稍作改編,這裡是用於 Bash 歷史反向搜尋的 Emacs 模式兼容鍵綁定Ctrl-R(未經測試):

if [[ ! -o vi ]]; then
 # Required to refresh the prompt after fzf
 bind '"\er": redraw-current-line'
 bind '"\e^": history-expand-line'

 # CTRL-R - Paste the selected command from history into the command line
 bind '"\C-r": " \C-e\C-u\C-y\ey\C-u$(HISTTIMEFORMAT= history | fzf-history)\e\C-e\er\e^"'
fi

引用自:https://unix.stackexchange.com/questions/523543