自訂 bash 用戶端歷史記錄重疊

自訂 bash 用戶端歷史記錄重疊

我正在編寫一個客戶端,用於透過 ssh 在 zimbra 伺服器上執行各種任務,但我遇到了一些障礙。這是代碼:

#!/bin/bash
set -e
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
export HISTCONTROL=ignoreboth

# History management
if [ -f $HOME/.zmcli_history ]; then
  history -r $HOME/.zmcli_history
else
  touch $HOME/.zmcli_history
  history -r $HOME/.zmcli_history
fi
trap "history -a $HOME/.zmcli_history && echo -e '\nExiting now.\n'" exit

# Styling
yellow='[33m'
bold='[1m'
off='[0m'

echo

# Client
while :; do
  read -ep "$bold${yellow}zimbra_cli[${off}server_domain$bold${yellow}]> $off" comm
  history -s "$comm"
done

注意:如果執行此腳本,它將在您的主目錄中建立歷史檔案 (.zmcli_history)。

一切都按預期進行,歷史記錄都在那裡,但當我繼續滾動歷史記錄時,以前的一些(通常很長)命令的部分通常仍然存在。這部分命令將充當會話其餘部分的提示的一部分,除非我按下 CTRL+L 來清除螢幕並將其重置為正常。我讀過許多文章,這些文章幫助了在 bash 終端機中遇到此問題的人。他們的問題是 PS1 格式不正確,而且 bash 對提示字串的長度感到困惑。這裡可能是類似的東西,但是這些解決方案不起作用,因為 read 命令不能使用那些轉義字符,例如 echo 可以(\e)。

我設法找到一種使用文字轉義(vim 插入模式下的 CTRL+V ESCAPE)來轉義顏色序列的方法。所以顏色有效,但我被這個歷史問題困住了。

我嘗試過的事情:

  • 命令替換 :: 以 echo -e 可以列印顏色代碼的方式寫入和轉義顏色代碼,然後在讀取命令 $(echo -e '\e[33m') 中回顯它。仍然看到顏色,但對解決歷史問題沒有幫助
  • 在顏色代碼周圍添加轉義的 [ 和 ]
  • 將帶有顏色代碼的整個提示放在讀取命令之前的單獨的 echo 命令中。缺點是,直到讀取命令之後(在另一個回顯中)我才能關閉格式,這意味著整個提示和命令將是粗體和彩色的。另外,如果我現在按 CTRL+L,連提示都會被清除,只剩下遊標

最後,由於我無法刪除歷史記錄,所以我嘗試刪除顏色。但這樣就不可能快速區分命令和輸出。

您可以透過啟動腳本並輸入 10-15 個長(亂碼)命令來重現問題。之後,嘗試上下滾動歷史記錄,您就會明白我在說什麼。

有人知道如何讓這項工作有效嗎?

答案1

你的劇本,就這樣,不允許我複製這個問題。只有在啟用顏色和這樣的閱讀線之後才開始變得混亂。作為記錄,我啟用了這些功能

# Styling
yellow=$'\e[33m'
bold=$'\e[1m'
off=$'\e[0m'

這是真的\[,但\]沒有幫助他們會在以下情況下這樣做PS1

但後來我發現這個答案。上面寫著

我打開info readline發現:

[...]
應用程式可能會指示提示包含在顯示時不佔用物理螢幕空間的字符,方法是將這些字符的序列與特殊標記 RL_PROMPT_START_IGNORERL_PROMPT_END_IGNORE(在 中聲明) 括起來readline.h。於終端的轉義序列。

正如我在其中搜索RL_PROMPT_START_IGNORERL_PROMPT_END_IGNORE定義的文本所說readline.h,然後找到:

/* Definitions available for use by readline clients. */
#define RL_PROMPT_START_IGNORE  '\001'
#define RL_PROMPT_END_IGNORE    '\002'

這導致我得出以下結論:

# Styling
yellow=$'\1\e[33m\2'
bold=$'\1\e[1m\2'
off=$'\1\e[0m\2'

它工作完美。

相關內容