On Linux, the easiest way to get the uptime in (fractional) seconds is via the 1st field of /proc/uptime
(see man proc
):
$ cut -d ' ' -f1 /proc/uptime
350735.47
To format that number the same way that w
and uptime
do, using awk
:
$ awk '{s=int($1);d=int(s/86400);h=int(s % 86400/3600);m=int(s % 3600 / 60);
printf "%d days, %02d:%02d\n", d, h, m}' /proc/uptime
4 days, 01:25 # 4 days, 1 hour, and 25 minutes
To answer the question as asked - parsing the output of w
(or uptime
, whose output is the same as w
's 1st output line, which contains all the information of interest), which also works on macOS/BSD, with a granularity of integral seconds:
A perl
solution:
<(uptime)
is a Bash process substitution that provides uptime
's output as input to the perl
command - see bottom.
$ perl -nle 'print for / up +((?:\d+ days?, +)?[^,]+)/' <(uptime)
4 days, 01:25
This assumes that days
is the largest unit every displayed.
perl -nle
tells Perl to process the input line by line, without printing any output by default (-n
), automatically stripping the trailing newline from each input line on input, and automatically appending one on output (-l
); -e
tells Perl to treat the next argument as the script (expression) to process.
print for /.../
tells Perl to output what each capture group (...)
inside regex /.../
captures.
up +
matches literal up
, preceded by (at least) one space and followed by 1 or more spaces (+
)
(?:\d+ days?, +)?
is a non-capturing subexpression - due to ?:
- that matches:
- 1 or more digits (
\d+
)
- followed by a single space
- followed by literal
day
, optionally followed by a literal s
(s?
)
- the trailing
?
makes the entire subexpression optional, given that a number-of-days part may or may not be present.
[^,]+
matches 1 or more (+
) subsequent characters up to, but not including a literal ,
([^,]
) - this is the hh:mm
part.
The overall capture group - the outer (...)
therefore captures the entire up-time expression - whether composed of hh:mm
only, or preceded by <n> day/s>
- and prints that.
<(uptime)
is a Bash process substitution (<(...)
)
that, loosely speaking, presents uptime
's output as a (temporary, self-deleting) file that perl
can read via stdin.