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

How to delete last two lines of an output using AWK?

我正在尝试制作一个输出的图形表示,显示当天服务器的可用内存(大约按小时显示),从该输出我不想要前两行和后两行,前两行我可以用 NR 轻松删除,虽然我在最后两行遇到了麻烦,但我发现的唯一方法是反转整个输出删除前两行,然后再次反转到正常状态。

有任何 better/correct 方法可以删除最后两行但在 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(( / 100000)*2 )"s", " "); 
    gsub(/ /, "#", LINE);
    print , LINE; } 
'

更新

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

echo 'graphics (freemem)'
echo 'GiB      0      500k      1M      1,5M'
sar -r | nawk '
    NR > 4 &&  !~ /Average/ &&  !~ /^$/ {
    LINE = sprintf("%" int(( * 2) / 100000 )"s", " "); 
    gsub(/ /, "#", LINE);
    print , 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 的结果。所以我想做的是通过计算将该列和 "translate" 数字作为“#”的条目,这样我以后就可以在图形表示中指定数据量。虽然,输出的开头和结尾有一些我不需要的行,所以我需要删除它们。

这是我现在的工作代码

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

您可以存储该行,做一些事情并在一段时间后打印,这样您就可以知道您是否在最后一行。但是当你有 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=[=12=]}'

这会换行,因此您在 prev_prev_line 中有两行之前的内容:

NR      [=13=]    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,因此您将最终处理从第一行到第 (NR-2) 行。

所以在 prev_prev_line 中你有两行前出现的行。这样,您就不会在输出中使用最后两行。

通过示例查看它是如何工作的:

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

如果没有别的办法

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

逃出 awk 以对文件进行一些计算

awk '{if (NR > 2 && NR < '$(( $(wc -l <$file) -1))')print [=10=]}' $file

如果记录数大于 2,我们将跳过前 2 行。如果它小于总行数减 1,则我们在最后两行之前停止(如果使用 <=,则可以使用 -2)。

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

鉴于您编辑的问题:

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