PS1提示以显示经过的时间


10

我目前使用它在bash提示中显示当前时间:

PS1=\[\e[0;32m\]\t \W>\[\e[1;37m\]

20:42:23 ~>

是否可以显示自上一个提示以来经过的时间?如:

00:00:00 ~> sleep 10
00:00:10 ~> sleep 20
00:00:20 ~>

这与是否有可能通过后台脚本定期更改PS1?



不,该帖子没有答案,我希望仅在显示新提示时,提示才会更改。
TeasingDart

确实没有可行的方法来完成您要问的事情,不。
DopeGhoti 2015年

1
如果显示的值是静态的(OP的问题似乎不允许这样做)是可行的。通过在shell变量中保存上一个时间的纪元时间,可以维持经过的时间。实施它似乎需要大量工作(一个小时左右-也许有人会提供比我所想的更简单的解决方案)。 这个问题会有所帮助。
托马斯·迪基

Answers:


10

一种实现方法是使用bash的PROMPT_COMMAND功能来执行修改PS1的代码。以下功能是我原始提交内容的更新版本;这个变量使用较少的两个环境变量,并在它们前面加上“ _PS1_”,以免破坏现有变量。

prompt_command() {
  _PS1_now=$(date +%s)
  PS1=$( printf "\[\e[0;32m\]%02d:%02d:%02d \W>\[\e[1;37m\] " \
           $((  ( _PS1_now - _PS1_lastcmd ) / 3600))         \
           $(( (( _PS1_now - _PS1_lastcmd ) % 3600) / 60 )) \
           $((  ( _PS1_now - _PS1_lastcmd ) % 60))           \
       )
  _PS1_lastcmd=$_PS1_now
}
PROMPT_COMMAND='prompt_command'
_PS1_lastcmd=$(date +%s)

将其放入您的.bash_profile中以开始操作。

请注意,您必须快速键入以使sleep参数与提示符参数相匹配-时间实际上是提示符之间的差异,包括键入命令所花费的时间。

00:00:02 ~> sleep 5   ## here I typed really quickly
00:00:05 ~> sleep 3   ## here I took about 2 seconds to enter the command
00:00:10 ~> sleep 30 ## more slow typing
00:01:35 ~>

后期添加:

基于@Cyrus现在删除的答案,这是一个不会因多余的变量而使环境混乱的版本:

PROMPT_COMMAND='
    _prompt(){
        PROMPT_COMMAND="${PROMPT_COMMAND%-*}-$SECONDS))\""
        printf -v PS1 "\[\e[0;32m\]%02d:%02d:%02d \W>\[\e[1;37m\] " \
                      "$(($1/3600))" "$((($1%3600)/60))" "$(($1%60))"
    }; _prompt "$((SECONDS'"-$SECONDS))\""

额外的后期添加:

从bash版本4.2echo $BASH_VERSION)开始,您可以避免date使用新的printf格式字符串进行外部调用;$(date +%s)$(printf '%(%s)T' -1)。代替件。从4.3版开始,您可以忽略该-1参数,以依赖于“ 现在没有参数”的行为。


这真的很接近。当我从bash提示符中复制/粘贴时,它可以工作,但是当我尝试将其添加到我的.bashrc中时,它会显示“ 1451424431:未找到命令”
TeasingDart 2015年

也许太多/太多被复制/粘贴了?
杰夫·谢勒

最后一个版本有效,正是我想要的!我认为这与我在设置提示后设置文字颜色的陷阱有关。谢谢。
TeasingDart

当您重置时,$SECONDS它不再跟踪自shell启动以来的时间
mikeserv

1
@chepner-好吧,可以肯定,但是它不会再花费时间了。不要误会我的意思-我赞成这个,因为这是一个很好的答案-但我认为$SECONDS为每个提示重新定义一个交互式shell 可能会引发意外行为。可能出于与评估运行时相关的任何原因而使用它的任何其他Shell函数将行为异常。
mikeserv

4
PS1[3]=$SECONDS
PS1='${PS1[!(PS1[1]=!1&(PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600))
   ]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]/60%60),  ${PS1[3]})):${PS1[1
   ]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]%60),     ${PS1[3]})):${PS1[1
   ]#${PS1[3]%%*??}0}$((PS1[3]=(SECONDS),       ${PS1[3]})):'$PS1

它通过计算处理格式-因此,尽管它确实扩展了数次,但它没有任何子shell或管道。

它只是$PS1当作数组使用,并使用较高的索引来存储/计算提示之间的任何/所有必要状态。没有其他外壳状态受到影响。

00:00:46:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:00:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:43:[mikeserv@desktop tmp]$ sleep 10
00:00:33:[mikeserv@desktop tmp]$ sleep 10
00:00:15:[mikeserv@desktop tmp]$
00:00:15:[mikeserv@desktop tmp]$
00:00:02:[mikeserv@desktop tmp]$
00:02:27:[mikeserv@desktop tmp]$

我可以分解一下...

首先,保存的当前值$SECONDS

PS1[3]=$SECONDS

接下来,$PS1[0]以在始终$PS1[1-3]进行自我引用的同时始终将正确的值设置为的方式定义为自我递归。为了获得这一部分,您必须考虑壳数学表达式的求值顺序。最重要的是,外壳数学始终是外壳数学的最后一项业务。首先,shell会扩展值。通过这种方式,您可以在使用赋值后在数学表达式中引用壳变量的旧值$

首先是一个简单的示例:

x=10; echo "$(((x+=5)+$x+x))" "$x"

40 15

Shell将通过首先替换使用美元符号引用的$x位置的值来评估该语句$,因此表达式变为:

(x+=5)+10+x

...然后,shell将的值加5 $x,然后将整个表达式扩展为x+10+x,同时仅将实际分配的值保留在引用变量中。因此,数学表达式的扩展值为40,但最终值为$x15。

$PS1除了在数组索引中进一步利用了数学扩展/评估功能之外,这在很大程度上也就是方程的工作方式。

PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'

我不太确定为什么选择在这里使用PS1[1]=!1-我想这可能只是愚蠢的美学-但这会$PS1[1]在扩展它进行参数替换时将0赋给。对于0以及其他任何值,按位AND的值将始终为0,但是&&当最左边的主数为0时,它不会像布尔值那样短路,因此每次仍需对括号表达式进行求值。当然,这很重要,因为第一个省略号是$PS1[2,3]设置初始值的地方。

无论如何,$PS1[1]即使在两次抽奖之间被w /篡改,这里也确保为0。在括号内...

PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600

... $PS1[2]分配了$PS1[3]和的差$SECONDS,并$PS1[3]分配了该值和3600的商。所有值都在此处初始化。所以:

${PS1[1]#${PS1[3]%%*??}0}

...如果其中至少有两位数字,$PS1[3]则内部扩展为null,并且因为我们知道$PS1[1]为0 $PS1[3],所以如果可以将其替换为空,则也将$PS1[1]其扩展为它的值。以这种方式,每次$PS1[3]分配的迭代只有一位数字值将扩展前导零,并且$PS1[3]其自身随后立即被模60扩展,同时为时,分,秒分别分配下一个连续较小的值。

漂洗并重复,直到最后一次迭代$PS1[3]被w的当前值覆盖为止,$SECONDS以便$SECONDS下次绘制提示时可以将其与再次进行比较。


1

到目前为止,我发现的最佳解决方案是:https : //github.com/jichu4n/bash-command-timer

[ 1s011 | May 25 15:33:44 BST ]该命令在执行命令后的右侧也打印了经过的时间,因此不会使您的PS1混乱。

整个字符串和时间格式是可配置的。甚至颜色和精度也是可配置的。我知道对于一些极简主义者来说可能有点多,但这确实很酷。

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.