Вы можете переписать этот текст, пропустив его через конвейер, который добавит жирный escape с красными escape-символами. Вы также можете изменить исходный код gnome-terminal в соответствии со своими потребностями. Нет выбора или настройка, которая достигла бы того, что вы описываете.
Для длительности менее 24 часов в ksh93
вы можете сделать:
$ TZ=UTC0 printf '%(%T.%3N)T\n' '#86399.99'
23:59:59.990
Переносимо, выполнение вычислений вручную относительно просто. И awk
с его математическими способностями и возможностями форматирования звучит как наиболее очевидный выбор:
$ awk -v t=123456789.123456 'BEGIN{
printf "%d:%02d:%06.3f\n", t/3600, (t/60)%60, t%60}'
34293:33:09.123
Как и в случае с вашим подходом printf
, у вас могут быть некоторые неожиданные результаты из-за округления:
$ awk -v t=59.9999 'BEGIN{
printf "%d:%02d:%06.3f\n", t/3600, (t/60)%60, t%60}'
0:00:60.000
Так что вы можете сделать:
$ awk -v t=599.9999 '
BEGIN{t=int(t*1000);
printf "%d:%02d:%02d.%03d\n", t/3600000, t/60000%60, t/1000%60, t%1000}'
0:09:59.999
Вы можете легко сделать это в обычном файле sh. Вы можете сделать код немного короче с датой GNU (надеюсь, вы не возражаете против округления миллисекунд в меньшую сторону, округление до ближайшего будет немного длиннее):
hours=$((${seconds%.*} / 3600))
min_s_nano=$(TZ=GMT date -d @$seconds +%M:%S.%N)
time_string=$hours:${min_s_nano%??????}
Дробная часть не влияет на количество часов, минут или секунд, поэтому вы можете просто оставить ее в стороне, выполнить вычисления без нее и добавить ее в конце. . Что-то вроде этого:
#!/bin/sh
seconds=16633.284
f=${seconds##*.}
if [ "$f" = "$seconds" ]; then f=0; fi
t=${seconds%.*}
s=$((t%60))
m=$((t/60%60))
h=$((t/60/60))
printf '%d:%02d:%06.3f\n' $h $m $s.$f
Вывод:
0 → 0:00:00.000
33. → 0:00:33.000
.21 → 0:00:00.210
60.394 → 0:01:00.394
8944.77 → 2:29:04.770
Это работает в любой sh-подобной оболочке (кроме некоторых древних до-POSIX).
Мой подход таков, используя dc
для выполнения вычислений:
seconds=16633.284
printf '%i:%02i:%06.3f\n' \
$(dc -e "$seconds d 3600 / n [ ] n d 60 / 60 % n [ ] n 60 % f")
printf, надеюсь, довольно знаком, но если нет, %i
означает целое число. %02i
означает дополнение целого числа начальным 0, если оно однозначное. %06.3f
— самый странный, но он означает 3 цифры после запятой и дополняется начальными нулями, если общая длина меньше 6 (включая десятичную точку).
Намеренно не заключенная в кавычки замена $(…)
дает эти три параметра, используя dc
:
Во-первых, push $seconds
фактическое число) в стек; дублировать его; затем разделите (с усечением) на 3600, чтобы получить часы. Нажмите и напечатайте это, затем нажмите пробел и напечатайте ([ ] n
).
В стеке остаются только секунды. Продублируйте его, разделите на 60 (опять усечение). Это дает минуты; возьми мод 60 чтобы выкинуть часы. Распечатайте его, опять же с пробелом. Оставив только секунды в стеке.
Наконец, mod 60, который дает только поле секунд, а в dc модуль полностью удовлетворяет десятичным дробям и сохраняет точность. f
затем печатает стек плюс новую строку.
Мы вызываем dc
и помещаем количество секунд в его стек и выполняем вычисления (сек ->ЧЧ/ММ/СС.МСЕК ), форматирование и отображение результатов.
seconds=16633.284
dc <<DC
# rearrange stack for number < 1hr
[r ldx q]sb
# rearrange stack for number < 1min
[rd ldxq]sc
# min++, sec-=60 hrs++, min-=60
[r1+r 60-d 60!>a]sa
# display result as h:mm:ss.sss
[n 58an 2lpx 58an 2lpx 46an 3lpx 10an]sd
# perform the conversion of seconds -> hours, minutes, seconds
[d60 >c lax r0rd60 >b lax r ldx]si
[
d1000* 1000% 1/r # fractional portion
1000* 1000/ 1/0r # integer portion
lix
]sh
# left zero-pad a number
[lk1+d sk 0n le >g ]sg
[sedZd sk le >gn]sp
# setup the number on the stack and begin computation
$seconds lhx
DC
0 --> 0:00:00.000
60.394 --> 0:01:00.394
8944.77 --> 2:29:04.770
86399.99 --> 23:59:59.990
59.9999 --> 0:00:59.999
599.9999 --> 0:09:59.999
16633.284 --> 4:37:13.284
33 --> 0:00:33.000
.21 --> 0:00:00.210
123456789.123456 --> 34293:33:09.123