<div dir="auto">_HHMMSS="19:09"<br></div><div dir="auto">_HHMMSS="19:08"<br></div><div dir="auto">IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}<br></div><div dir="auto">if [[ ${_SEKNDS_ARL} -eq2 ]]; then<br></div><div dir="auto">_SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))<br></div><div dir="auto">echo "// __ \$_SEKNDS: |${_SEKNDS}|"<br></div><div dir="auto">fi<br></div><div dir="auto"><br></div><div dir="
<div dir="auto"><br></div><div dir="auto">lbrtchx<br></div> </body> </html>
Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:
_HHMMSS="19:09"
_HHMMSS="19:08"
IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}
if [[ ${_SEKNDS_ARL} -eq 2 ]]; then
_SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))
echo "// __ \$_SEKNDS: |${_SEKNDS}|"
fi
bash: _SEKNDS + 08: value too great for base (error token is "08")
Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:
_HHMMSS="19:09" means 19*60 + 9 = 1149 seconds
_HHMMSS="19:08" means 19*60 + 8 = 1148 seconds
so, it seems date is also somehow parsing that value as octal even though it is being formatted in a date friendly way. is there a way to exactly specify the encoding of the input for date?
Video durations are formatted in youtube's .info.json files as "HH:MM:SS";
_HHMMSS="19:09"
_HHMMSS="19:08"
IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}
if [[ ${_SEKNDS_ARL} -eq 2 ]]; then
_SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))
echo "// __ \$_SEKNDS: |${_SEKNDS}|"
fi
bash: _SEKNDS + 08: value too great for base (error token is "08")
On Fri, Jul 18, 2025 at 01:21:08AM +0200, lbrtchx@tutamail.com wrote:
OK, the Math is right, but the assumptions made by date aren't smart. I "overtested" your one liner with the kinds of input you would grab using jq from youtube .info.json files
and to my amazement, when you only have two semicolon separated values, the bash date utility assumes the first chunk to be the hours and the second the minutes!:
I am not at all surprised. It could have been either HH:MM or MM:SS. I think that HH:MM is reasonable/correct - but I will not argue. But you now know how it
interprets it so simply detect the NN:NN case and append :00
OK, the Math is right, but the assumptions made by date aren't smart. I "overtested" your one liner with the kinds of input you would grab using jq from youtube .info.json files
and to my amazement, when you only have two semicolon separated values, the bash date utility assumes the first chunk to be the hours and the second the minutes!:
echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"<br></div><div dir="auto"><br></div><div dir="auto">_HHMMSS="00:19:08"<br></div><div dir="auto">seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )<br></div><div dir="auto">echo "// __ \$_HHMMSS|$_HHMMSS|, seconds=$seconds"<br></div><div dir="auto"><br></div><div dir="auto">_HHMMSS="19:09"<br></div><div dir="auto">seconds=$( TZ=GMT date --date="1 january 1970 $_HHMMSS" "+%s" )<br></div><div dir="auto">echo "// __ \$_HHMMSS|$_HHMMSS|,
<div dir="auto">// __ $_HHMMSS|19:09:00|, seconds=68940<br></div><div dir="auto">// __ $_HHMMSS|19:08:00|, seconds=68880<br></div><div dir="auto">// __ $_HHMMSS|00:19:09|, seconds=1149<br></div><div dir="auto">// __ $_HHMMSS|00:19:08|, seconds=1148<s reply when I get the chance. I still think that there should be a way to make what I need straight forward using date's own formatting.<br></div><div dir="auto"> lbrtchx</div><div dir="auto"><br></div> </body>
</div><div dir="auto">// __ $_HHMMSS|19:09|, seconds=68940<br></div><div dir="auto">// __ $_HHMMSS|19:08|, seconds=68880<br></div><div dir="auto">$ <br></div><div dir="auto">~<br></div><div dir="auto"> I will have to go over, learn from Greg'
OK, it makes some more sense now. The range of digits in the octal
system is from 0 to 7, so it would complain with "08" and "09" (but
not with "10" which would then be "8" in octal), but why would command
line utilities assume you are encoding numeric values as octal? Now I
notice many people have stumble on the same problem. There should be a straight forward way to encode from "HH:MM:SS" to seconds. I doubt
that the date utility would assume you are computing numbers as
octal.
On Jul 18, 2025, lbrtchx@tutamail.com wrote:
OK, it makes some more sense now. The range of digits in the octal
system is from 0 to 7, so it would complain with "08" and "09" (but
not with "10" which would then be "8" in octal), but why would command
line utilities assume you are encoding numeric values as octal? Now I notice many people have stumble on the same problem. There should be a straight forward way to encode from "HH:MM:SS" to seconds. I doubt
that the date utility would assume you are computing numbers as
octal.
As I recall, this is a holdover from languages that predate C that an explicit leading zero indicated octal notation.
Decimal 7 => 7
Octal 7 => 07
Character 7 => '7'
As far as the code goes, I'd rather start from scratch.
On Friday, July 18, 2025 12:52:03 AM CEST, Greg Wooledge wrote:
As far as the code goes, I'd rather start from scratch.
just out of curiosity:
i don't like fix global return values (like $r in your code). i'd rather
give the function a variable name to put the result in.
do you have any objections to doing this in bash?: ======================================================================== #!/bin/bash
# $1: name of variable to put the result in
# $2...#n: parameters optional for whatever the function does
myfunc ()
{
# do something... or not...
printf -v "$1" "%s..." "..." ...
}
Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:
_HHMMSS="19:09"
_HHMMSS="19:08"
IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}
if [[ ${_SEKNDS_ARL} -eq 2 ]]; then
_SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))
echo "// __ \$_SEKNDS: |${_SEKNDS}|"
fi
bash: _SEKNDS + 08: value too great for base (error token is "08")
~
yet, it works for _HHMMSS={"3:54:14", "20:01", "20:00", "19:07", "19:06", "19:05", ... } and all other similar conversion?!
lbrtchx
E.g.:
printf 01:02:03 | (IFS=: read h m s; printf '%s\n' $(( $((h * 3600)) +
$((m * 60)) + $s )))
$((m * 60)) + $s )))bash: 08: value too great for base (error token is "08")
On Fri, Jul 18, 2025 at 13:16:17 -0700, Michael Paoli wrote:
E.g.:
printf 01:02:03 | (IFS=: read h m s; printf '%s\n' $(( $((h * 3600)) +
$((m * 60)) + $s )))
You still need to strip leading zeroes.
hobbit:~$ echo 01:08:09 | (IFS=: read h m s; printf '%s\n' $(( $((h * 3600)) +
$((m * 60)) + $s )))bash: 08: value too great for base (error token is "08")
echo $(( $(echo 07:08:09 | sed -e 's/^0*\([0-9]\)/3600 * \1 + /;s/:0*\([0-9]:\)/60 * \1/;s/:0*\([0-9]\)$/ + \1/;') ))
On Fri, Jul 18, 2025 at 18:59:06 -0700, Michael Paoli wrote:
echo $(( $(echo 07:08:09 | sed -e 's/^0*\([0-9]\)/3600 * \1 + /;s/:0*\([0-9]:\)/60 * \1/;s/:0*\([0-9]\)$/ + \1/;') ))
This one is missing some * operators. You're only capturing a single
digit in each segment, but there could be two digits (or maybe even
more in the first segment).
hobbit:~$ echo $(( $(echo 07:18:19 | sed -e 's/^0*\([0-9]\)/3600 * \1 + /;s/:0*\([0-9]:\)/60 * \1/;s/:0*\([0-9]\)$/ + \1/;') ))
bash: 3600 * 7 + :18:19 : syntax error: operand expected (error token is ":18:19 ")
Realistically, though, why are people so *bent* on writing "one-liners"?
It's less efficient and less readable than the straightforward code.
Longer code is not worse. It's often better.
A mathematical trick may be used instead even if external processes like sed are considered as undesired overhead
for i in 0 09 008 59 080; do i1=1$i; i2=2$i; echo "$i = $((2*i1 - i2))";
done
0 = 0
09 = 9
008 = 8
59 = 59
080 = 80
echo \
$((
$(
d12='\([0-9]\{1,2\}\)'
echo 09:10:11 |
sed -e '
s/^/ /
s/:/ /g
s/ 0*\([0-9]\)/ \1/g
'" s/^ $d12 $d12 $d12"'$/3600 * \1 + 60 * \2 + \3/
'
)
))
Video durations are formatted in youtube's .info.json files as "HH:MM:SS"; so, I went monkey and did the conversion myself, but I got two errors which I can't make sense of whatsoever with only two values:
_HHMMSS="19:09"
_HHMMSS="19:08"
IFS=$(echo -en "\n\b"); _SEKNDS_AR=($(echo "${_HHMMSS}" | tr ':' '\n')); _SEKNDS_ARL=${#_SEKNDS_AR[@]}
if [[ ${_SEKNDS_ARL} -eq 2 ]]; then
_SEKNDS=$(( 60 * ${_SEKNDS_AR[0]} )); _SEKNDS=$(( _SEKNDS + ${_SEKNDS_AR[1]} ))
echo "// __ \$_SEKNDS: |${_SEKNDS}|"
fi
bash: _SEKNDS + 08: value too great for base (error token is "08")
~
yet, it works for _HHMMSS={"3:54:14", "20:01", "20:00", "19:07", "19:06", "19:05", ... } and all other similar conversion?!
lbrtchx
I have no idea to which degree the following is portable:
strip_zeroes() { zeroes="${1%%[!0]*}"; printf '%s\n' "${1#"$zeroes"}"; }
However what
I am really afraid of is
https://mywiki.wooledge.org/BashPitfalls#pf46
46. read num; echo $((num+1))
Always validate your input (see BashFAQ/054) before using num in an arithmetic context as it allows code injection.
$ echo 'a[$(echo injection >&2)]' | bash -c 'read num; echo $((num+1))' injection
1
JavaScript (browser dev tools console)
009 === 9 // => true
parseInt("009") // => 9
010 === 8 // => true
parseInt("010") // => 10
On Fri, Jul 18, 2025 at 21:08:09 -0700, Michael Paoli wrote:
echo \
$((
$(
d12='\([0-9]\{1,2\}\)'
echo 09:10:11 |
sed -e '
s/^/ /
s/:/ /g
s/ 0*\([0-9]\)/ \1/g
'" s/^ $d12 $d12 $d12"'$/3600 * \1 + 60 * \2 + \3/
'
)
))
I don't like this one as much. It's better than the original one-liner
(both because it's actually correct -- I think! -- and because it's in
a format that's a little bit easier to read), but it still looks like
it was written by someone who is bound and determined to use sed for this,
no matter how difficult it may be.
Also, the use of [0-9]\{1,2\} for the first segment means you're
hard-capping this to 99:59:59 and will never be able to handle 100:23:45. That might be OK, or not. I don't know whether there are any restrictions
on the durations the OP is dealing with. I would've used \{1,\} to
remove the two-digit limit, if I had to do it this way.
iirc, i think i have read in your wiki to NOT have variable names with leading underscores...
On Fri, Jul 18, 2025 at 12:34:36 +0200, Michael wrote:
On Friday, July 18, 2025 12:52:03 AM CEST, Greg Wooledge wrote: ...
Bash 4.3 and higher have nameref variables, [...]
The advantage of nameref variables is that they can also refer to
arrays as well as strings. If you need to return an array, this is
the way you'd want to go (unless you're targeting older systems).
Both ways work, with one important caveat. If the function doesn't use
any local variables at all, then these approaches work perfectly well. However, things start to become ugly if the function uses local variables
and the caller passes a variable name that collides with one of them.
There is unfortunately *no* way at all to define a local reference to
a variable in a different scope. You're at the mercy of bash's
dynamic scoping rules.
The only workaround for that is to make all of your local variables
obscure, so that the caller is unlikely to duplicate them. Prefixing
every local variable with something like _myfunc_ (underscore,
function name, underscore) is one way to ensure a lack of collisions,
as long as the caller doesn't go out of their way to cause breakage. Obviously, this makes the code uglier.
On Mon, Jul 21, 2025 at 13:37:33 +0200, Michael wrote:
iirc, i think i have read in your wiki to NOT have variable names
with leading underscores...
If you restrict yourself to never using variable names beginning with
_ in normal situations, then that gives you the opportunity to use
it as a pseudo-namespace delimiter in this unusual situation.
I'm not sure which page you're referring to specifically, but
generally the convention is that if you begin a variable name with _
then it has some special meaning or significance, which is up to you
to define. The basic idea is that if you create a variable name of
this form, you can be fairly confident that it doesn't collide with
anything, but this only works if you follow a consistent convention.
If *all* your variable names begin with _ then you're just a
lunatic. (Yes, I've seen people do this. No, I have no clue why.)
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 546 |
Nodes: | 16 (2 / 14) |
Uptime: | 146:05:00 |
Calls: | 10,383 |
Calls today: | 8 |
Files: | 14,054 |
D/L today: |
2 files (1,861K bytes) |
Messages: | 6,417,699 |