如何使用AWK删除输出的最后两行?

时间:2016-04-14 11:47:05

标签: bash unix awk ksh nawk

我正在尝试对输出进行图形表示,该输出显示当天服务器的可用内存(以小时为单位显示),从该输出我不想要前两行和后两行,前两个我可以轻松删除NR,虽然我遇到了最后两个问题,我找到的唯一方法是反转整个输出删除前两行然后再将其反转到正常状态。

删除最后两行但更好/正确的方法是在AWK中进行吗?

这就是我到目前为止所做的工作。

echo 'graphics (freemem)'
echo 'GiB      0      500k      1M      1,5M'
sar -r | tail -r | awk 'NR > 2{ print }' | tail -r | nawk '
    NR > 4{
    LINE = sprintf("%" int(($2 / 100000)*2 )"s", " "); 
    gsub(/ /, "#", LINE);
    print $1, LINE; } 
'

更新

所以我以另一种方式做到了,因为它会更容易阅读脚本并且它对我有用,但是对于任何其他需要这样做的人来说,使用我之前做过的方式,或者下面那些人的方式已经回答了。

echo 'graphics (freemem)'
echo 'GiB      0      500k      1M      1,5M'
sar -r | nawk '
    NR > 4 && $1 !~ /Average/ && $1 !~ /^$/ {
    LINE = sprintf("%" int(($2 * 2) / 100000 )"s", " "); 
    gsub(/ /, "#", LINE);
    print $1, LINE; } 
'

更新2

所以我想要做的是监控数据的图形表示,此输出每小时更新一次,请记住,在一天的不同时间,行的长度会有所不同。这就是我得到的sar -r的实际输出。

.
SunOS doc 5.10

00:00:00 freemem freeswap
01:00:01 1624430 19474799
02:00:00 1624421 19474738
03:00:00 1624413 19474683
04:00:00 1624527 19475309
05:00:00 1624525 19475290
06:00:00 1624517 19475232
07:00:01 1624510 19475176
08:00:00 1624503 19475120
08:20:00 1539793 18771472
08:40:00 1509924 18535201
09:00:00 1500681 18492050
09:20:00 1494254 18435535
09:40:00 1479623 18266664
10:00:00 1486372 18317241
10:20:00 1480565 18269032
10:40:00 1479030 18260247
11:00:01 1476462 18237731
11:20:00 1475999 18234221
11:40:00 1478854 18259827
12:00:00 1478223 18254861
12:20:00 1482956 18294572
12:40:00 1479061 18260565
13:00:00 1470463 18185441
13:20:00 1474090 18217961
13:40:00 1478585 18257393
14:00:00 1478219 18255445
14:20:00 1474327 18223749
14:40:00 1470468 18190676
15:00:00 1471941 18204282
15:20:00 1474138 18223380
15:40:00 1471698 18202561
16:00:00 1470316 18191099
16:20:00 1467203 18163653
16:40:00 1468943 18179148

Average  1549994 18855701

所以我们不关心freeswap,我们不使用它。我们只关心freemem的结果。所以我要做的是将列作为条目并通过计算将数字“转换”为“#”,以便稍后我可以指定图形表示中的数据量。虽然,在输出的开头和结尾都有我不需要的行,所以我需要删除它们。

这是我现在的工作代码

echo '\ngraphics (freemem)'
echo 'GiB      0      500k      1M      1,5M'
sar -r | awk 'NR > 2 {print P2} {P2=P; P=$0}' |
nawk '
    NR > 4 {
    LINE = sprintf("%" int(($2 * 2) / 100000 )"s", " "); 
    gsub(/ /, "#", LINE);
    print $1, LINE; } 
'

所以正确的输出就是这个:

graphics (freemem)
GiB      0      500k      1M      1,5M
01:00:01 ################################
02:00:00 ################################
03:00:00 ################################
04:00:00 ################################
05:00:00 ################################
06:00:00 ################################
07:00:01 ################################
08:00:00 ################################
08:20:00 ##############################
08:40:00 ##############################
09:00:00 ##############################
09:20:00 #############################
09:40:00 #############################
10:00:00 #############################
10:20:00 #############################
10:40:00 #############################
11:00:01 #############################
11:20:00 #############################
11:40:00 #############################
12:00:00 #############################
12:20:00 #############################
12:40:00 #############################
13:00:00 #############################
13:20:00 #############################
13:40:00 #############################
14:00:00 #############################
14:20:00 #############################
14:40:00 #############################
15:00:00 #############################
15:20:00 #############################
15:40:00 #############################
16:00:00 #############################
16:20:00 #############################

4 个答案:

答案 0 :(得分:3)

$ seq 5 | awk 'NR>2{print p2} {p2=p; p=$0}'
1
2
3

鉴于您编辑过的问题:

$ cat tst.awk
BEGIN {
    print "\ngraphics (freemem)"
    print "GiB      0      500k      1M      1,5M"
}
/^[0-9: ]+$/ {
    line = sprintf("%*s", int(($2*2)/100000), "")
    gsub(/ /,"#",line)
    print $1, line
}

$ awk -f tst.awk file

graphics (freemem)
GiB      0      500k      1M      1,5M
01:00:01 ################################
02:00:00 ################################
03:00:00 ################################
04:00:00 ################################
05:00:00 ################################
06:00:00 ################################
07:00:01 ################################
08:00:00 ################################
08:20:00 ##############################
08:40:00 ##############################
09:00:00 ##############################
09:20:00 #############################
09:40:00 #############################
10:00:00 #############################
10:20:00 #############################
10:40:00 #############################
11:00:01 #############################
11:20:00 #############################
11:40:00 #############################
12:00:00 #############################
12:20:00 #############################
12:40:00 #############################
13:00:00 #############################
13:20:00 #############################
13:40:00 #############################
14:00:00 #############################
14:20:00 #############################
14:40:00 #############################
15:00:00 #############################
15:20:00 #############################
15:40:00 #############################
16:00:00 #############################
16:20:00 #############################
16:40:00 #############################

答案 1 :(得分:2)

您可以存储该行,执行操作并在一段时间后打印,以便您可以知道您是否在最后一行。但是当你拥有像headtail这样的工具时,那就太多了。

将输出传递给head,然后再将其传递给awk

head -n -2

测试

$ seq 10
1
2
3
4
5
6
7
8
9
10
$ seq 10 | head -n -2
1
2
3
4
5
6
7
8

由于您没有允许您执行此操作的GNU头,因此可以使用awk保存变量:

awk '{if (prev_prev_line) print prev_prev_line; prev_prev_line=prev_line}
     {prev_line=$0}'

这会改变行,这样你就可以在prev_prev_line中获得前两行的内容:

NR      $0    prev_line   prev_prev_line
 1      1      -             -
 2      2      1             -
 3      3      2             1
 4      4      3             2
 ....
 NR-1   NR-1   NR-2          NR-3
 NR     NR     NR-1          NR-2

因此,由于您正在使用prev_prev_line,因此您最终将处理从第1行到第(NR-2)行。

所以在prev_prev_line中你有两行之前发生过的那一行。这样,您不会在输出中使用最后两行。

通过示例了解它是如何工作的:

$ awk '{if (prev_prev_line) print NR,prev_prev_line; prev_prev_line=prev_line}
         {prev_line=$0}' < <(seq 10)
3 1
4 2
5 3
6 4
7 5
8 6
9 7
10 8

答案 2 :(得分:2)

如果没有其他工作

... | sed '$d' | sed '$d'

答案 3 :(得分:1)

退出awk以对文件进行一些数学计算

awk '{if (NR > 2 && NR < '$(( $(wc -l <$file) -1))')print $0}' $file

如果记录编号大于2,我们已跳过前2行。如果它小于总行数减1,我们就会在最后两行之前停止(如果使用&lt; =,则可以使用-2。)