判断 PROMPT_COMMAND 中最后一个命令是否为空

判断 PROMPT_COMMAND 中最后一个命令是否为空

在 bash 中,从 PROMPT_COMMAND 内部,有没有办法判断用户是否只是按了“返回”而没有输入命令?

答案1

检查历史编号是否增加。取消的提示或用户刚刚按下的提示Enter不会增加历史记录编号。

历史编号在变量 中可用HISTCMD,但在 中 不可用PROMPT_COMMAND(因为你想要的实际上是上一个命令的历史编号;执行PROMPT_COMMAND本身的命令没有历史编号)。您可以从 的输出中获取数字fc

prompt_command () {
  HISTCMD_previous=$(fc -l -1); HISTCMD_previous=${HISTCMD_previous%%$'[\t ]'*}
  if [[ -z $HISTCMD_before_last ]]; then
    # initial prompt
  elif [[ $HISTCMD_before_last = "$HISTCMD_previous" ]]; then
    # cancelled prompt
  else
    # a command was run
  fi
  HISTCMD_before_last=$HISTCMD_previous
}
PROMPT_COMMAND='prompt_command'

请注意,如果您打开了历史记录中的重复项压缩(HISTCONTROL=ignoredupsHISTCONTROL=erasedups),则在连续运行两个相同的命令后,这将错误地报告空命令。

答案2

有一个解决方法,但它有一些要求:

您需要设置$HISTCONTROL为保存所有命令,包括重复项和空格。所以设置:

HISTCONTROL=

现在定义一个要调用的函数$PROMPT_COMMAND

isnewline () {
  # read the last history number
  prompt_command__isnewline__last="$prompt_command__isnewline__curr"
  # get the current history number
  prompt_command__isnewline__curr="$(history 1 | grep -oP '^\ +\K[0-9]+')"
  [ "$prompt_command__isnewline__curr" = "$prompt_command__isnewline__last" ] && \
    echo "User hit return"
}

现在,设置$PROMPT_COMMAND变量:

PROMPT_COMMAND="isnewline"

查看输出:

user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$ 

答案3

我不知道有什么方法可以做到这一点本身。但你可以通过使用获得相同的效果

陷阱一些命令或函数调试

这将导致some_command_or_function任何时候运行命令时都会被调用。棘手的是,如果您只是点击,它不会被调用Enter- 除非您定义了 PROMPT_COMMAND,在这种情况下,点击Enter会调用 PROMPT_COMMAND,进而触发陷阱。

也许实现您想要的结果的最简单方法是定义调试陷阱函数而不是使用 PROMPT_COMMAND。但我不能说,因为我不知道你想要什么结果。如果您希望在点击 时发生一些事情Enter,并且在键入命令时发生不同/额外的事情,那么(AFAIK)您需要使用调试陷阱和 PROMPT_COMMAND。看这个答案和 这个 寻找一种使这两种机制很好地协同工作的方法。

答案4

(如果我被允许添加评论,这将是对已接受答案的评论......)@schlimmen,您可以设置HISTTIMEFORMAT为类似的内容HISTTIMEFORMAT='%F %T ',然后保存并比较history 1。这是因为使用erasedups,至少(可能重复的)最后一个命令的时间戳每次都会改变——并且通过HISSTIMEFORMAT适当的设置,history 1将显示时间戳(与 不同fc),因此即使在重复的命令之间也是不同的。

相关内容