Reputation: 3914
This is about a time string in the format accepted by the common linux command sleep
,
like "3d 7h 5m 10s" (3 days, 7 hours, 5 minutes and 10 seconds),
which would have to result in:
(3 * 24 * 60 * 60) + (7 * 60 * 60) + (5 * 60) + 10 = 284710
seconds
Note that not all these 4 elements must be present, nor in the right order, and one element might appear multiple times. So "3s 5s 6h" is valid too, and should result in:
(6 * 60 * 60) + (3 + 5) = 21608
seconds
Upvotes: 2
Views: 884
Reputation: 51
The Walter A answer on this question can be enhanced.
To be compatible with Mac OS and other platforms it is better to enable ERE mode (-E flag) for sed. With enabling ERE, we should always escape plus sign in the regexp part of the rule (see here). Also, we don't need to escape plus sign in the replacement part of the rule.
So, here is the fixed t2s
bash function:
t2s() {
sed -E 's/d/*24*3600 +/g; s/h/*3600 +/g; s/m/*60 +/g; s/s/+/g; s/\+[ ]*$//g' <<< "$1" | bc
}
Tests:
$ t2s "60m"
3600
$ t2s "1h50m50s"
6650
Upvotes: 0
Reputation: 4026
In the rare case you don't have bc
available:
(perhaps bash-on-Windows like I suffer with?)
Then the @WalterA function t2s
can be changed to this:
t2s() {
eq=$(sed 's/d/*24*3600 +/g; s/h/*3600 +/g; s/m/*60 +/g; s/s/\+/g; s/+[ ]*$//g' <<< "$1")
((val=eq))
echo "$val"
}
Upvotes: 1
Reputation: 3914
A bash function based solution that supports days, hours, minutes and seconds.
file sleepTimeToSeconds
:
#!/bin/bash
# Converts a time string like "2h 3m 3s" to the amount of seconds
function timeToSeconds() {
timeStr="$@"
# validate
grep -Pqx '( *\d+[smhd] +)+' <<< "$timeStr "
if [ $? != 0 ]
then
>&2 echo "error: Bad time format"
exit 1
fi
secs=0
for timePart in $timeStr
do
timeType=${timePart//[[:digit:]]/}
timeAmount=${timePart//[[:alpha:]]/}
toSecsFactor=0
case "$timeType" in
s|'')
toSecsFactor=1
;;
m)
toSecsFactor=60
;;
h)
let toSecsFactor="60 * 60"
;;
d)
let toSecsFactor="60 * 60 * 24"
;;
*)
>&2 echo "Bad time string type: '$timeType'"
exit 2
;;
esac
let secs="$secs + ( $timeAmount * $toSecsFactor )"
done
echo -n $secs
}
timeToSeconds "$@"
test:
> sleepTimeToSeconds "5s 4s 1d 2h 3m"
93789
Upvotes: 1
Reputation: 20022
When you replace the letters with the corresponding factors, you can pipe that to bc
. You only need to take care of the +
at the end of the line.
t2s() {
sed 's/d/*24*3600 +/g; s/h/*3600 +/g; s/m/*60 +/g; s/s/\+/g; s/+[ ]*$//g' <<< "$1" | bc
}
Testrun
$ t2s "3d 7h 5m 10s"
284710
$ t2s "3d 7h 5m "
284700
$ t2s "3s 5s 6h"
21608
Upvotes: 6
Reputation: 27235
I don't know if there is a predefined command that fits your requirements, but I came up with a more compact and loop-free script using GNU grep
, paste
, and bc
.
Usage examples, assuming the script is saved as t2sec
:
t2sec 3s
prints 3
.t2sec "2m 1s"
, t2sec "1s 2m"
, t2sec "1m 1s 1m"
all print 121
.t2sec "1s 2s"
, t2sec "1s2s"
, t2sec 1s 2s
, t2sec " 1s 2s "
all print 3
.t2sec
, t2sec ""
, t2sec "1x"
, t2sec "s"
all print nothing and exit with status of 1.#! /bin/bash
t="$*"
# validate
grep -Pqx '( *\d+[smhd])+ *' <<< "$t" || exit 1
# helper functions
sumAndMultiply() { bc <<< "(0$(paste -s -d+))*$1"; }
xToSeconds() { grep -Po "\\d+(?=$1)" | sumAndMultiply "$2"; }
# convert to seconds
(
xToSeconds s 1 <<< "$t";
xToSeconds m 60 <<< "$t";
xToSeconds h 3600 <<< "$t";
xToSeconds d 86400 <<< "$t";
) | sumAndMultiply 1
Upvotes: 1