如何从文件中读取前n行和后n行?

Ami*_*mir 4 bash awk sed tail head

我想知道如何读取文件的前n行和最后n行?因为n=2,我在网上看到它(head -n2 && tail -n2)会起作用,但事实并非如此.

$ cat x
1
2
3
4
5
$ cat x | (head -n2 && tail -n2)
1
2
Run Code Online (Sandbox Code Playgroud)

预期的产出n=2将是:

1
2
4
5
Run Code Online (Sandbox Code Playgroud)

srd*_*srd 7

head -n2 file && tail -n2 file
Run Code Online (Sandbox Code Playgroud)

  • UUOC.`head -n2 x && tail -n2 x` (2认同)
  • 如果文件长度不超过 3 行,则不会产生正确的输出。 (2认同)

Ed *_*ton 3

您很可能想要类似的东西:

... | awk -v OFS='\n' '{a[NR]=$0} END{print a[1], a[2], a[NR-1], a[NR]}'
Run Code Online (Sandbox Code Playgroud)

或者,如果您需要指定一个数字,并考虑到 @Wintermute 的敏锐观察,您不需要缓冲整个文件,那么您真正想要的是这样的:

... | awk -v n=2 'NR<=n{print;next} {buf[((NR-1)%n)+1]=$0}
         END{for (i=1;i<=n;i++) print buf[((NR+i-1)%n)+1]}'
Run Code Online (Sandbox Code Playgroud)

我认为数学是正确的 - 希望您明白使用由 NR 索引的旋转缓冲区,该缓冲区按缓冲区的大小进行修改,并调整为使用 1-n 范围内的索引而不是 0-(n-1) 。

为了帮助理解上面索引中使用的模运算符,下面是一个带有中间打印语句的示例,用于显示执行时的逻辑:

$ cat file   
1
2
3
4
5
6
7
8
Run Code Online (Sandbox Code Playgroud)

$ cat tst.awk                
BEGIN {
    print "Populating array by index ((NR-1)%n)+1:"
}
{
    buf[((NR-1)%n)+1] = $0

    printf "NR=%d, n=%d: ((NR-1 = %d) %%n = %d) +1 = %d -> buf[%d] = %s\n",
        NR, n, NR-1, (NR-1)%n, ((NR-1)%n)+1, ((NR-1)%n)+1, buf[((NR-1)%n)+1]

}
END { 
    print "\nAccessing array by index ((NR+i-1)%n)+1:"
    for (i=1;i<=n;i++) {
        printf "NR=%d, i=%d, n=%d: (((NR+i = %d) - 1 = %d) %%n = %d) +1 = %d -> buf[%d] = %s\n",
            NR, i, n, NR+i, NR+i-1, (NR+i-1)%n, ((NR+i-1)%n)+1, ((NR+i-1)%n)+1, buf[((NR+i-1)%n)+1]
    }
}
$ 
$ awk -v n=3 -f tst.awk file
Populating array by index ((NR-1)%n)+1:
NR=1, n=3: ((NR-1 = 0) %n = 0) +1 = 1 -> buf[1] = 1
NR=2, n=3: ((NR-1 = 1) %n = 1) +1 = 2 -> buf[2] = 2
NR=3, n=3: ((NR-1 = 2) %n = 2) +1 = 3 -> buf[3] = 3
NR=4, n=3: ((NR-1 = 3) %n = 0) +1 = 1 -> buf[1] = 4
NR=5, n=3: ((NR-1 = 4) %n = 1) +1 = 2 -> buf[2] = 5
NR=6, n=3: ((NR-1 = 5) %n = 2) +1 = 3 -> buf[3] = 6
NR=7, n=3: ((NR-1 = 6) %n = 0) +1 = 1 -> buf[1] = 7
NR=8, n=3: ((NR-1 = 7) %n = 1) +1 = 2 -> buf[2] = 8

Accessing array by index ((NR+i-1)%n)+1:
NR=8, i=1, n=3: (((NR+i = 9) - 1 = 8) %n = 2) +1 = 3 -> buf[3] = 6
NR=8, i=2, n=3: (((NR+i = 10) - 1 = 9) %n = 0) +1 = 1 -> buf[1] = 7
NR=8, i=3, n=3: (((NR+i = 11) - 1 = 10) %n = 1) +1 = 2 -> buf[2] = 8
Run Code Online (Sandbox Code Playgroud)