Форматировать и отображать интервал с дробными секундами в оболочке

Вы можете переписать этот текст, пропустив его через конвейер, который добавит жирный escape с красными escape-символами. Вы также можете изменить исходный код gnome-terminal в соответствии со своими потребностями. Нет выбора или настройка, которая достигла бы того, что вы описываете.

4
20.05.2017, 15:50
5 ответов

Для длительности менее 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
1
27.01.2020, 20:46

Вы можете легко сделать это в обычном файле sh. Вы можете сделать код немного короче с датой GNU (надеюсь, вы не возражаете против округления миллисекунд в меньшую сторону, округление до ближайшего будет немного длиннее):

hours=$((${seconds%.*} / 3600))
min_s_nano=$(TZ=GMT date -d @$seconds +%M:%S.%N)
time_string=$hours:${min_s_nano%??????}
3
27.01.2020, 20:46

Дробная часть не влияет на количество часов, минут или секунд, поэтому вы можете просто оставить ее в стороне, выполнить вычисления без нее и добавить ее в конце. . Что-то вроде этого:

#!/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).

7
27.01.2020, 20:46

Мой подход таков, используя 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 затем печатает стек плюс новую строку.

3
27.01.2020, 20:46

Мы вызываем 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
1
27.01.2020, 20:46

Теги

Похожие вопросы