我目前使用它在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 ~>
我目前使用它在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 ~>
Answers:
一种实现方法是使用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.2(echo $BASH_VERSION
)开始,您可以避免date
使用新的printf格式字符串进行外部调用;$(date +%s)
用$(printf '%(%s)T' -1)
。代替件。从4.3版开始,您可以忽略该-1
参数,以依赖于“ 现在没有参数”的行为。
$SECONDS
它不再跟踪自shell启动以来的时间
$SECONDS
为每个提示重新定义一个交互式shell 可能会引发意外行为。可能出于与评估运行时相关的任何原因而使用它的任何其他Shell函数将行为异常。
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,但最终值为$x
15。
$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
下次绘制提示时可以将其与再次进行比较。
到目前为止,我发现的最佳解决方案是:https : //github.com/jichu4n/bash-command-timer
[ 1s011 | May 25 15:33:44 BST ]
该命令在执行命令后的右侧也打印了经过的时间,因此不会使您的PS1混乱。
整个字符串和时间格式是可配置的。甚至颜色和精度也是可配置的。我知道对于一些极简主义者来说可能有点多,但这确实很酷。