在 Linux 上,我试图获得一个代表可用系统内存的最终用户友好字符串。
示例:
Your computer has 4 GB of memory.
我认为这些方面最终用户友好(您可能不同意):
1G
比1.0G
更具可读性(1
Vs 1.0
)
1GB
比1G
更具可读性(GB
Vs G
)
1 GB
比1GB
(space-separated
计量单位)更具可读性
memory
比RAM
,DDR
或DDR3
(无行话)更具可读性
来自 free 的 procps-ng 实用程序有一个适用于人类的选项:
-h, --human
Show all output fields automatically scaled to shortest three digit unit
and display the units of print out. Following units are used.
B = bytes
K = kilos
M = megas
G = gigas
T = teras
If unit is missing, and you have petabyte of RAM or swap, the number is
in terabytes and columns might not be aligned with header.
所以我决定从那里开始:
> free -h
total used free shared buffers cached
Mem: 3.8G 1.4G 2.4G 0B 159M 841M
-/+ buffers/cache: 472M 3.4G
Swap: 4.9G 0B 3.9G
3.8G
听起来很有希望所以我现在要做的就是......
过滤包含人类可读字符串的行的输出(即Mem:
)
从行中间挑出内存总量(即3.8G
)
解析数量和度量单位(即3.8
和G
)
根据我的喜好格式化并显示字符串(例如G
↝GB
,...)
free -h | \
awk '/^Mem:/{print $2}' | \
perl -ne '/(\d+(?:\.\d+)?)(B|K|M|G|T)/ && printf "%g %sB\n", $1, $2'
输出:
3.8 GB
我更喜欢使用 gawk ,但我不知道如何
使用更好的,甚至规范(如果有的话)解析字符串中的“float”
我不介意“只是公认的大小字母”(B|K|M|G|T)
的挑剔匹配,即使这会因为引入新尺寸而不必要地破坏匹配< / p>
我使用%g
将4.0
输出为4
,这可能是您不同意的,具体取决于您对这些评论的看法:https://unix.stackexchange.com/a/70553/10283。
awk
执行上述操作?perl
可以写得比这更优雅,保持严格吗?记住:
I am a beginner robot. Here to learn. :]
总结为了我自己的利益:如果可以的话,巩固学习。
使用 regex character classes ,而非 regex alternation ,从集合中挑选一个字符
perl 有一个-a
选项,可将$_
从-e
或-n
拆分为{{1} }}:
例如, gawk :
@F
可以在 perl :
中这样写出来echo foo bar baz | awk '{print $2}'
除非等同于 gawk 的echo foo bar baz | perl -ane 'print "$F[1]\n";'
,否则我认为我还是喜欢 gawk 更好,但当然要做 perl 中的所有事情,既更清洁又更有效。(有相同的吗?)
编辑:实际上,这证明存在,并且--field-separator
就像在 gawk 中一样:
-F
输出:
echo ooxoooxoooo | perl -Fx -ane 'print join "\n", @F'
oo
ooo
oooo
选项,非常棒:将其视为 Python 的 str.rstrip (如果您不是 Python 负责人,请参阅链接)了解-l
的有效性,但会重新附加{{1}您自动输出谢谢,安迪!
答案 0 :(得分:3)
是的,我确定你只能这样做,但我是一个Perl家伙,所以这就是你如何做Perl-only。
而不是(B|K|M|G|T)
使用[BKMGT]
。
使用Perl的-l
自动从输入中删除换行符并将其添加到输出中。
我认为没有任何理由让Awk做一些剥离,Perl做其余的事情。您可以使用Perl的-a。
对字段进行自动分割我不知道free -h
的输出是什么(我的free
没有-h
选项)所以我猜这个
free -h | \
perl -alne'/^Mem:/ && ($F[1]=~/(\d+(?:\.\d+)?)[BKMGT]/) && printf( "%g %sB", $1, $2)'
答案 1 :(得分:2)
awk (实际上是 gawk )解决方案
free -h | awk 'FNR == 2 {if (match($2,"[BKMGT]$",a)) r=sprintf("%.0f %sB",substr($2,0,RSTART-1), a[0]); else r=$2 " B";print "Your computer has " r " of memory."}'
或细分以便于阅读
free -h | awk 'FNR == 2 {if (match($2,"[BKMGT]$",a)) r=sprintf("%.0f %sB",
substr($2,0,RSTART-1), a[0]); else r=$2 " B";
print "Your computer has " r " of memory."}'
其中
FNR
是n th 行(如果2
执行{}
命令)$2
是2 nd 字段if
(条件)命令; else
命令; match
(字符串,正则表达式,匹配数组)。正则表达式说&#34;必须以BKMGT&#34; r=sprintf
将变量r
设置为 sprintf ,%.0f
为无小数点浮动RSTART
告知比赛发生的位置,a[0]
是第一场比赛输出上面的例子
Your computer has 4 GB of memory.
答案 2 :(得分:0)
另一个冗长的Perl答案:
free -b |
perl -lane 'if(/Mem/){ @u=("B","KB","MB","GB"); $F[2]/=1024, shift @u while ($F[2]>1024); printf("%.2f %s", $F[2],$u[0])}'