Re: Is there a POSIX compliant way of turning a "HH:MM:SS" formatted string to seconds? ...
On 20/07/2025 09:45, Greg Wooledge wrote:
On Sun, Jul 20, 2025 at 09:02:37 +0700, Max Nikulin wrote:
I have no idea to which degree the following is portable:
strip_zeroes() { zeroes="${1%%[!0]*}"; printf '%s\n' "${1#"$zeroes"}"; }
That's POSIX compliant. It's very similar to the first examples on
<https://mywiki.wooledge.org/BashFAQ/067>:
Reading <https://mywiki.wooledge.org/ArithmeticExpression> I was
confused by: "Bash can also use an extended glob (see FAQ #67 for more
information)". I expected that the FAQ entry scope is namely extended
glob. Perhaps it is better to move the link earlier with more general
description, e.g. "Various approaches how to strip leading zeroes are
discussed in FAQ #67".
I have a strong dislike for functions that "return" things by writing
to stdout, and expect you to capture that output using a command
substitution, because every command substitution creates a forked process.
Not to mention the fact that command substitution alters the captured
output (by stripping all trailing newlines).
I admit, JS examples were a kind of trolling (see below), but this
function was not added to insult you. I decided that it helps to
separate the code and the list of examples I used to test it. Balance of
efficiency and self documented code that may be augmented by unit tests
should be evaluated for every case.
I have seen new ${command;} and ${|command;} bashisms in news related to
5.3 release, but I have not dug into details when they might be helpful
to avoid forks. (Not to mention that it is out of the scope of this
"POSIX" thread and bookworm.)
Yes. Bash is a complete disaster when it comes to safety.
[...]
Examples of acceptable validation:
[[ $x = +([0-9]) ]] || die "input must be a number"
hmsglob='+([0-9]):[0-9][0-9]?(:[0-9][0-9])'
[[ $input = $hmsglob ]] || die "input must be M:SS or H:MM:SS"
I would consider some middle ground with minimal, but portable pattern
despite it allows :0:0:0:0:0
for i in "1:a:10" "01:02:00" ":0:0:0:0:0"; do
printf "'%s' " "$i";
if [ -n "${i##*[!0-9:]*}" ]; then echo safe; else echo unsafe; fi ;
done
'1:a:10' unsafe
'01:02:00' safe
':0:0:0:0:0' safe
JavaScript (browser dev tools console)
009 === 9 // => true
parseInt("009") // => 9
010 === 8 // => true
parseInt("010") // => 10
I won't even ask.
Legacy. It is possible to make "0" prefix invalid in literals.
(function() { "use strict"; return 010; })()
// => SyntaxError: "0"-prefixed octal literals are deprecated; use the
"0o" prefix instead
(function() { "use strict"; return 0o10; })()
// => 8
Even earlier it was recommended to explicitly specify base for parseInt
parseInt("010", 10)
On 20/07/2025 11:06, Michael Paoli wrote:
specified HH:MM:SS format for input, nothing more, nothing
less. And sure, we should validate input and, e.g. throw error if input
isn't valid.
[...]
Also, the earlier context,
YouTube video durations, also not likely we'll be dealing
with > 99H 59M 59S video durations.
Degree of strictness of a validator should be reasonable if
implementation allows some relaxed rules.
Others have suggested, e.g. python. Certainly python or perl or the
like could be used, code would be more concise, but system overhead
would generally be significantly larger.
Code style is quite specific to remind threads like
https://lists.debian.org/msgid-search/CAFakBwj6a0N7+3hHQSX_SfQKAL4a-Peifyx9tTPZWqDLR1KS+w@mail.gmail.com
so likely it is a custom tool to archive web sites (that should run
namely from a read-only media, DVD-R). That is why I see little point in
struggling with shell.
case "$# $1" in
1\ [0-9][0-9]:[0-9][0-9]:[0-9][0-9])
:
;;
*)
1>&2 printf '%s\n' \
"${0##*/}: usage, requires single argument in format HH:MM:SS, aborting"
exit 1
;;
esac
I do not thing that 1:02:03 should be rejected.
Reply to: