Bash:“历史编号”与“命令编号”

Lag*_*ian 12 command-line bash command-history

在谷歌搜索如何通过 PS1 变量自定义我的 shell 提示时,我看到了可以使用的特殊字符表。特别是:

          \!     the history number of this command
          \#     the command number of this command
Run Code Online (Sandbox Code Playgroud)

“历史编号”似乎更常用,我知道如何使用命令,例如!523从历史记录中重做命令。但我无法弄清楚“命令编号”是否具有类似的功能。我试过放入\#我的 PS1 变量,它似乎输出了在特定会话中输入的命令数(不像\!,它在注销/退出后仍然存在)。

任何人都知道如何以方便或有意义的方式使用“命令编号”?

ana*_*cat 6

据我所知(您的研究似乎证实了这一点),无法以交互方式或不通过fc!n快捷方式引用该神奇数字。那些当然似乎只指历史列表中的绝对位置,而不是自此特定 shell 启动以来的相对位置(\#正如您正确指出的那样,指的是 waht )。

我发现在这里做得更好的唯一方法是设置以下内容:

export HISTFILESIZE=1001
export HISTSIZE=-1
Run Code Online (Sandbox Code Playgroud)

那样:

  1. 新会话的历史记录从 开始1000,这样可以更轻松地识别我在会话中的位置
  2. (有点无关)我不会在给定的会话中丢失旧的历史记录(但仍然不会淹没文件)

基本上,它将我修改后的提示 ( PS1="\\!$ ") 从:

499$ 
Run Code Online (Sandbox Code Playgroud)

到:

1000$ 
Run Code Online (Sandbox Code Playgroud)

...这使它在开始时更干净一些。但这可能不是您要寻找的答案。:)

(顺便说一句,我还查看了 zsh 以寻找解决方案,它似乎根本没有等效的\#,所以这也无济于事。)


bis*_*hop 2

Bash 的命令编号仅用于显示。

首先,一些背景bashref

命令编号和历史编号通常是不同的:命令的历史编号是它在历史列表中的位置,其中可能包括从历史文件恢复的命令(*note Bash History Facilities::),而命令编号是在当前 shell 会话期间执行的命令序列中的位置。

深入查看源代码,parse.y我们看到它'\#'解析为全局静态变量current_command_number

case '#':                                                                     
  n = current_command_number;                                                 
  /* If we have already incremented current_command_number (PS4,              
 ${var@P}), compensate */                                                     
  if (orig_string != ps0_prompt && orig_string != ps1_prompt && orig_string != ps2_prompt)
n--;                                                                          
  temp = itos (n);                                                            
  goto add_string;                                                            
Run Code Online (Sandbox Code Playgroud)

它只有一种用途:在 中eval.c,它在运行命令时递增:

# ...
current_command_number++;                                                  

executing = 1;                                                             
stdin_redir = 0;                                                           

execute_command (current_command);                                         
Run Code Online (Sandbox Code Playgroud)

保留的只是一个数字,而不是实际的命令,甚至不是等效的历史编号。因此,在执行每个命令时,bash 会忘记哪个命令与哪个命令编号相关联,从而导致命令编号无法用于除显示和滚动引用之外的任何用途。