从 "w" 命令输出中提取正常运行时间值
Extract the uptime value from "w" command output
如何从 linux 上的以下命令获取 up
的值?
# w
01:16:08 up 20:29, 1 user, load average: 0.50, 0.34, 0.30
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 00:57 0.00s 0.11s 0.02s w
# w | grep up
01:16:17 up 20:29, 1 user, load average: 0.42, 0.33, 0.29
鉴于正常运行时间的格式取决于它是少于还是多于 24 小时,我能想到的最好的是双倍 awk
:
$ w
18:35:23 up 18 days, 9:08, 6 users,...
$ w | awk -F 'user|up ' 'NF > 1 {print }' \
| awk -F ',' '{for(i = 1; i < NF; i++) {printf("%s ",$i)}} END{print ""}'
18 days 9:08
类似这样的 gnu sed:
$ w |head -n1
02:06:19 up 3:42, 1 user, load average: 0.01, 0.05, 0.13
$ w |sed -r '1 s/.*up *(.*),.*user.*//g;q'
3:42
$ echo "18:35:23 up 18 days, 9:08, 6 users, load average: 0.09, 0.31, 0.41" \
|sed -r '1 s/.*up *(.*),.*user.*//g;q'
18 days, 9:08
在 Linux 上,获得正常运行时间(小数)[=80=]秒[的最简单方法=105=] 通过 /proc/uptime
的第一个字段(参见 man proc
):
$ cut -d ' ' -f1 /proc/uptime
350735.47
要像 w
和 uptime
一样格式化该数字,使用 awk
:
$ awk '{s=int();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
回答问题 - 解析 w
的输出( 或 uptime
,其输出与 w
的第一行输出相同,其中包含所有感兴趣的信息), 也适用于 macOS/BSD,粒度为 积分秒:
一个perl
解决方案:
<(uptime)
是一个 Bash 进程替换,提供 uptime
的输出作为 perl
命令的输入 - 见底部。
$ perl -nle 'print for / up +((?:\d+ days?, +)?[^,]+)/' <(uptime)
4 days, 01:25
这假设 days
是每个显示的最大单位。
perl -nle
告诉 Perl 逐行处理输入,默认情况下不打印任何输出 (-n
),自动从输入的每个输入行中去除尾随换行符, 并自动在输出上附加一个 (-l
); -e
告诉 Perl 将下一个参数视为要处理的脚本(表达式)。
print for /.../
告诉 Perl 输出正则表达式 /.../
中每个捕获组 (...)
捕获的内容。
up +
匹配文字 up
,前面(至少)一个 space,后面跟着 1 个或多个 spaces (+
)
(?:\d+ days?, +)?
是一个 非捕获 子表达式 - 由于 ?:
- 匹配:
- 1 位或更多位 (
\d+
)
- 后跟一个 space
- 后跟文字
day
,可选择后跟文字 s
(s?
)
- 结尾的
?
使整个子表达式 可选 ,因为天数部分可能存在也可能不存在。
[^,]+
匹配 1 个或多个 (+
) 个后续字符,但不包括文字 ,
([^,]
) - this是 hh:mm
部分。
整体捕获组 - 外部 (...)
因此捕获整个正常运行时间表达式 - 无论仅由 hh:mm
组成,还是由 <n> day/s>
组成 -并打印出来。
<(uptime)
是一个 Bash process substitution (<(...)
)
笼统地说,将 uptime
的输出呈现为一个(临时的、自删除的)文件,perl
可以通过标准输入读取该文件。
如何从 linux 上的以下命令获取 up
的值?
# w
01:16:08 up 20:29, 1 user, load average: 0.50, 0.34, 0.30
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 00:57 0.00s 0.11s 0.02s w
# w | grep up
01:16:17 up 20:29, 1 user, load average: 0.42, 0.33, 0.29
鉴于正常运行时间的格式取决于它是少于还是多于 24 小时,我能想到的最好的是双倍 awk
:
$ w
18:35:23 up 18 days, 9:08, 6 users,...
$ w | awk -F 'user|up ' 'NF > 1 {print }' \
| awk -F ',' '{for(i = 1; i < NF; i++) {printf("%s ",$i)}} END{print ""}'
18 days 9:08
类似这样的 gnu sed:
$ w |head -n1
02:06:19 up 3:42, 1 user, load average: 0.01, 0.05, 0.13
$ w |sed -r '1 s/.*up *(.*),.*user.*//g;q'
3:42
$ echo "18:35:23 up 18 days, 9:08, 6 users, load average: 0.09, 0.31, 0.41" \
|sed -r '1 s/.*up *(.*),.*user.*//g;q'
18 days, 9:08
在 Linux 上,获得正常运行时间(小数)[=80=]秒[的最简单方法=105=] 通过 /proc/uptime
的第一个字段(参见 man proc
):
$ cut -d ' ' -f1 /proc/uptime
350735.47
要像 w
和 uptime
一样格式化该数字,使用 awk
:
$ awk '{s=int();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
回答问题 - 解析 w
的输出( 或 uptime
,其输出与 w
的第一行输出相同,其中包含所有感兴趣的信息), 也适用于 macOS/BSD,粒度为 积分秒:
一个perl
解决方案:
<(uptime)
是一个 Bash 进程替换,提供 uptime
的输出作为 perl
命令的输入 - 见底部。
$ perl -nle 'print for / up +((?:\d+ days?, +)?[^,]+)/' <(uptime)
4 days, 01:25
这假设 days
是每个显示的最大单位。
perl -nle
告诉 Perl 逐行处理输入,默认情况下不打印任何输出 (-n
),自动从输入的每个输入行中去除尾随换行符, 并自动在输出上附加一个 (-l
);-e
告诉 Perl 将下一个参数视为要处理的脚本(表达式)。print for /.../
告诉 Perl 输出正则表达式/.../
中每个捕获组(...)
捕获的内容。up +
匹配文字up
,前面(至少)一个 space,后面跟着 1 个或多个 spaces (+
)(?:\d+ days?, +)?
是一个 非捕获 子表达式 - 由于?:
- 匹配:- 1 位或更多位 (
\d+
) - 后跟一个 space
- 后跟文字
day
,可选择后跟文字s
(s?
) - 结尾的
?
使整个子表达式 可选 ,因为天数部分可能存在也可能不存在。
- 1 位或更多位 (
[^,]+
匹配 1 个或多个 (+
) 个后续字符,但不包括文字,
([^,]
) - this是hh:mm
部分。整体捕获组 - 外部
(...)
因此捕获整个正常运行时间表达式 - 无论仅由hh:mm
组成,还是由<n> day/s>
组成 -并打印出来。
<(uptime)
是一个 Bash process substitution (<(...)
) 笼统地说,将uptime
的输出呈现为一个(临时的、自删除的)文件,perl
可以通过标准输入读取该文件。