告诉在PROMPT_COMMAND中最后一个命令是否为空


12

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

Answers:


7

检查历史记录号是否增加。取消的提示或用户刚刚按下的提示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)中的重复数据压缩,那么在连续运行两个相同的命令后,这将错误地报告一个空命令。


谢谢,吉尔斯。我在这里想念东西。这似乎从来没有运行过,因为尽管PROMPT_COMMAND ='echo hello'可以,但是在文字函数的第一行上放置'echo hello'却行不通。我认为这可能是HISTCMD_previous与HISTCMD_PREVIOUS的问题,但是没有问题。我会继续戳,但我要评论,因为您的bash fu显然超出了我。
用户

@user我修复了更多的错字,特别是该${HISTCMD_previous%%$'[\t ]'*}位丢失了,$'…'并在`, t`或空格之后而不是在制表符或空格之后被截断,但是bash打印了一个制表符。
吉尔斯(Gillles)“所以-别再作恶了”

1
该解决方案基于以下假设:重复项已保存在历史记录中(对我而言这是关闭的)。因此,此解决方案无法满足重复命令的预期要求,而重复项没有保存在历史记录中。
schlimmchen

4

有一种解决方法,但是有一些要求:

您需要设置$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:~$ 

我不明白您为什么在这里使用临时文件。last从一次调用isnewline到下一次调用保留该变量(只能选择一个不太通用的名称,prompt_command__isnewline__last以避免冲突)。
吉尔(Gilles)'所以

@Gilles您说得对,我更改了,谢谢您的建议
混乱

谢谢,混乱。我在以下内容中使用了相同的想法,这更容易解析。 HISTCONTROL="" function last_was_blank { local last_command="$(history 1)" if [[ "$last_was_blank_PREVIOUS_LINE" = "$last_command" ]] ; then echo "true" else echo "false" fi export last_was_blank_PREVIOUS_LINE="$last_command" } PROMPT_COMMAND=last_was_blank
用户

1

我不知道的方式做到这一点,本身。但是您可以通过使用获得相同的效果

捕获some_command_or_function调试

这将导致some_command_or_function被称为运行命令的任何时间。棘手的事情是,如果您刚刚命中,它将不会被调用Enter-除非您定义了PROMPT_COMMAND,在这种情况下,命中会Enter调用PROMPT_COMMAND,从而触发陷阱。

达到所需结果的最简单方法可能是定义调试陷阱函数,而不是使用PROMPT_COMMAND。但是我不能说,因为我不知道你想要什么结果。如果您想在单击时发生某些事情Enter,而在键入命令时又发生其他事情,那么(AFAIK)您需要使用调试陷阱和PROMPT_COMMAND。见这个答案和  这一个 的方法,使这两个机制一起玩很好。


0

(如果允许我添加评论,这将是对已接受答案的评论...)@schlimmen,您可以设置HISTTIMEFORMATHISTTIMEFORMAT='%F %T ',然后保存并比较history 1。这是因为,至少每次擦除时(可能重复的)最后一次命令的时间戳都会被擦除,并且-并进行HISSTIMEFORMAT适当设置,history 1将显示时间戳(与不同fc),因此即使重复的命令之间也有所不同。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.