I'm building a script to automate some audio file editing with ffmpeg, but I'm currently having to add and subtract time values by hand. How can I do this programmatically? Like:
$ foo 1:45.5 + 1:30.2
3:15.7
I'm building a script to automate some audio file editing with ffmpeg, but I'm currently having to add and subtract time values by hand. How can I do this programmatically? Like:
$ foo 1:45.5 + 1:30.2
3:15.7
This awk program can accept an arbitrary number of operands.
The syntax is a bit strict, a space is mandatory between operand and operators, i.e. "1+1" does not work. Also, it should be made more robust against malformed time intervals by improving the regexp.
$ 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
If you want to skip leading zero fields, replace the last line with this:
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
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
}' <<< "$*"
}
Edit 1: Hours added
Edit 2: Sum and subtract operators added
Create an sh
file:
$ 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}'
Expected output:
$ 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
Please refer to this post for awk usage https://stackoverflow.com/a/2181764/14320738.
Does this answer your question?