我正在寻找一种检查AIX上进程内存使用情况的方法,并找到了this page,列出了这个命令:
# svmon -Pt15 | perl -e 'while(<>){print if($.==2||$&&&!$s++);$.=0 if(/^-+$/)}'
它适用于我的目的,但我想了解Perl单线部分是如何工作的。
我知道它正在解析svmon
命令的输出。我已经理解了输出第二行的$.==2
部分。部件$.=0
会重置行号,以便它可以对svmon
列出的每个流程执行相同的处理。
但是,我无法理解||$&&&!$s++
部分。有OR。 $&
是匹配的部分(什么?)和&amp;&amp;是AND运算符,但我不确定我是否正确分解它。
svmon
返回(没有任何重定向)每个进程的类似行块。第一行类似于:
# svmon -Pt15 | head -n 20
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd 16MB
12058652 java 579432 8261 397386 824106 Y Y N
PageSize Inuse Pin Pgsp Virtual
s 4 KB 67560 309 1610 40138
m 64 KB 31992 497 24736 48998
Vsid Esid Type Description PSize Inuse Pin Pgsp Virtual
c86b4c 7e work text data BSS heap m 4096 0 43 4096
c30d43 7f work text data BSS heap m 4096 0 215 4096
db2358 68 work text data BSS heap m 4089 0 3667 4096
d25056 69 work text data BSS heap m 4057 0 585 4096
99d59b 1002 work text data BSS heap m 3461 0 2061 4082
b531b1 7d work text data BSS heap m 3440 0 39 3440
a551a7 1001 work text data BSS heap m 2933 0 2597 3767
970017 90000000 work shared library text m 2172 0 213 2413
ca3c48 6a work text data BSS heap m 2090 0 2006 4096
ade32e 4 work text or shared-lib code seg sm 25389 0 0 25389
... (tons of lines)
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd 16MB
6094910 java 494585 8110 5754 484444 Y Y N
PageSize Inuse Pin Pgsp Virtual
s 4 KB 31257 158 1610 16780
m 64 KB 28958 497 259 29229
Vsid Esid Type Description PSize Inuse Pin Pgsp Virtual
a31ba7 8 work text or shared-lib code seg m 4096 0 0 4096
da3159 6 work text or shared-lib code seg m 4096 0 0 4096
... repeated several times
带有perl部分的已处理输出返回标题,虚线和每个进程一行,以及命令和内存详细信息:
# svmon -Pt15 | perl -e 'while(<>){print if($.==2||$&&&!$s++);$.=0 if(/^-+$/)}'
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd 16MB
12058652 java 579438 8261 397386 824106 Y Y N
6094910 java 494583 8110 5754 484444 Y Y N
5046378 java 382458 8217 5738 339847 Y Y N
21102818 java 352534 8149 5738 305644 Y Y N
18219048 java 321394 8081 176586 340617 Y Y N
18612404 java 235323 8161 100746 267565 Y Y N
3735554 java 195412 8118 125306 222885 Y Y N
24772644 java 185403 8209 88474 202652 Y Y N
25559102 java 143341 8095 5738 118094 Y Y N
11272240 java 137082 8193 82810 167151 Y Y N
18874550 java 131531 8129 79898 144249 Y Y N
5505082 java 121320 8075 50922 136195 Y Y N
答案 0 :(得分:5)
perl -e 'while(<>){print if($.==2||$&&&!$s++);$.=0 if(/^-+$/)}'
这看起来 - 乍一看 - 就像打算每隔一行打印一样,也是---
行之后的第一行。让我们来看看这些部件。
while(<>) { ... }
以逐行模式读取标准输入(或文件,如果提供参数)。在单行中执行此操作的最常见方法是使用-n
或-p
开关。即这样:
perl -e 'while(<>) { ... }'
与此相同:
perl -ne ' ... '
print if
将打印$_
,其中一条读取行,如果其后的条件为真。条件if ( $. == 2 || $& && !$s++ )
是一块笨重的马粪。让我们剖析它。
首先,让我们注意它由两个语句组成,与||
连接,这意味着如果其中一个语句为真,则整个语句为真。其次,请注意它是短路的,这意味着如果左边的声明为真,则永远不会评估右手声明。由于计数器变量$s
,这与此相关。
$.
是访问的最后一个输入文件句柄上的行号的内置变量。它可以被操纵,但上帝知道为什么会这样。在这种情况下,如果行号为2
,则会打印该行。
如果$.
不是2
,则会检查右侧语句。它也是一个链式语句,&&
,意味着两者都必须为真。实际上,所有三个语句都是相互链接的:a || b && c
,这使得operator precedence变得相当混乱。幸运的是(?),它似乎意味着我们认为它意味着:(a || (b && c))
。因此,如果$&
为真,并且!$s++
为真,那么打印就会通过。变量右侧的increment operator在递增之前返回值,在这种情况下,它在第一次运行代码时返回0
,否则变为{ {1}},一个真正的价值。之后的所有时间,1
都返回false。这是一个常见的Perl习惯用法,仅对第一个遇到的值返回true。
唷!
如果有一行只包含短划线!$s++
,那么之后的部分会将$.
重置为0
。据推测,这是为了分离&#34;记录&#34;,例如:
----
但这引出了为什么foo
bar
------
next
...
的问题?我们是否总是打印每条记录的第二行?我们总是打印第一行是#34;而不是第2行&#34;,前面是一行&#34;只是&#34;破折号!$s++
。
所以让我们试试并总结......这将打印
----
之后的第2行,如果之间没有任何短划线可以用更简单,更健壮的方式完成相同的结果吗?
哦,是的,当然。这是一个做同样事情的例子,但是使用更简单的工具:
----
这基本上就像英语一样,总是很好。它需要前三行并打印它们,然后检查&#34;虚线&#34;,丢弃后面的行,然后打印下一行。我使用连接运算符$ perl -ne'if ($. <= 3) { print } elsif (/^-+$/) { <>; print <>.""; }'
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd 16MB
12058652 java 579432 8261 397386 824106 Y Y N
6094910 java 494585 8110 5754 484444 Y Y N
99058652 java 579432 8261 397386 824106 Y Y N
22058652 java 579432 8261 397386 824106 Y Y N
将文件句柄放在标量上下文中,只打印一行。另一种方法是使用标量变量并打印出来。
这是最好的方法吗?嗯......这是一个简单的方法。您可以通过创建程序文件来改进它,该程序文件将运行如下:
.
将它与linux系统的便捷功能相结合,您可以使用新的命令。
该计划可能是这样的:
svmon -Pt15 | perl program.pl
答案 1 :(得分:1)
您正在正确分解它,因为我们可以使用B::Deparse进行验证:
perl -MO=Deparse,-p -e 'while(<>){print if($.==2||$&&&!$s++);$.=0 if(/^-+$/)}'
while (defined(($_ = <ARGV>))) {
((($. == 2) || ($& && (!($s++)))) and print($_));
(/^-+$/ and ($. = 0));
}
$&
包含最后一个匹配项,在这种情况下,只有一个匹配位置:/^-+$/
。
!$s++
仅在$s++
为假时,即在第一场比赛($& && !$s++
)时才为真。