【问题标题】:How to add/subtract sexagesimal time values in Bash?如何在 Bash 中添加/减去六十进制时间值?
【发布时间】:2021-09-15 22:06:20
【问题描述】:

我正在构建一个脚本来自动使用 ffmpeg 编辑一些音频文件,但我目前不得不手动添加和减去时间值。我怎样才能以编程方式做到这一点?喜欢:

$ foo 1:45.5 + 1:30.2
3:15.7

【问题讨论】:

  • 你可以参考这个。-- stackoverflow.com/questions/38491986/…
  • date 本身可以处理分数,并且是一种很好的“语言”,可以将秒数转换为时间线(人类可读;-))输出。试试这个 shell 函数:dtlfe(){(date --date="${1}" +'date time line format example%n%H:%M:%S.%N')} 并使用:dtlfe @-3600.0000000001
  • 当结果大于 60 分钟,甚至 24 小时时会发生什么?例如,59:00.0 + 1:00.0 的预期输出是什么?
  • @Socowi 59:00 + 1:00 应该等于 1:00:00。 AV 编辑并没有真正处理几天,所以在这种情况下 24:00:00 + 1:00:00 应该等于 25:00:00。

标签: bash


【解决方案1】:

另一种 AWK 解决方案

这个 awk 程序不仅可以接受两个操作数。

语法有点严格,操作数和运算符之间必须有空格,即“1+1”不起作用。 此外,还应通过改进正则表达式使其对格式错误的时间间隔更加稳健。

$ cat timesum.awk
BEGIN {
  FS = ":"
  RS = " "
  sum = 0
  sign = "+"
}

/[+-]/ {
  sign = $0
}

/[[:digit:]]+/ {
  b = (sign == "+") ? 1 : -1
  for (i=NF; i>0; --i) {
    sum += $i * b
    b *= 60
  }
}

END {
  if (sum < 0) {
    sum = -sum
    printf "-"
  }
  printf "%d:%02d:%06.3f\n", sum/3600, sum%3600/60, sum%60
}

一些例子:

$ awk -f timesum.awk <<< "1:59:59.1 + 0.9"
2:00:00.000
$ awk -f timesum.awk <<< "20 + 20 + 20"
0:01:00.000
$ awk -f timesum.awk <<< "20 + 20 - 40"
0:00:00.000
$ awk -f timesum.awk <<< "1:00 - 1:00:00"
-0:59:00.000

编辑

如果您想跳过前导零字段,请将最后一行替换为:

  mf = "%d:"
  sf = "%.3f\n"
  if (sum >= 3600) {
    printf "%d:", sum/3600
    mf = "%02d:"
  }
  if (sum >= 60) {
    printf mf, sum%3600/60
    sf = "%06.3f\n"
  }
  printf sf, sum%60

编辑 2

这是您可以在现有 bash 脚本中包含和使用的版本:
function timecalc() { awk '
BEGIN { FS = ":"; RS = " "; base = 1 }
/^\+$/ { base = 1 }
/^-$/ { base = -1 }
/[[:digit:]]+/ {
  for (i=NF; i>0; --i) { sum += $i * base; base *= 60 }
  base = 1 # assume + if operand is missing
}
END {
  if (sum < 0) { sum = -sum; printf "-" }
  printf "%d:%02d:%06.3f\n", sum/3600, sum%3600/60, sum%60
}' <<< "$*"
}

【讨论】:

    【解决方案2】:

    awk 解决方案

    修改 1:添加小时数

    编辑 2:添加了加减运算符

    创建一个sh 文件:

    $ cat calctime.sh 
    #!/bin/bash
    first=$1
    operator=$2
    second=$3
    printf "$first:$second" |
    awk -F: -v oper=$operator '{ 
        if(oper=="+") 
            secs = (60*($1+$3) + ($2+$4));
        else if(oper=="-") 
            secs = ((60*$1+$2) - (60*$3+$4));
        if(secs>=3600)
            printf "%02d:%02d:%s\n", secs/3600, secs%3600/60, secs%60;
        else    
            printf "%02d:%s\n", secs%3600/60, secs%60}'
    

    预期输出:

    $ sh calctime.sh 40:25.4 - 25:10.7
    15:14.7
    $ sh calctime.sh 40:25.4 + 25:10.7
    01:05:36.1
    $ sh calctime.sh 8:51.5 + 25:10.7
    34:2.2
    

    awk 用法请参考这篇文章https://stackoverflow.com/a/2181764/14320738

    这能回答你的问题吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-27
      • 2015-01-27
      • 2017-03-26
      • 1970-01-01
      相关资源
      最近更新 更多