命令显示文件的前几行和最后几行

mtk*_*mtk 25 logs tail text-processing cat head

我有一个包含多行的文件,每一行的开头都有一个时间戳,例如

[Thread-3] (21/09/12 06:17:38:672) logged message from code.....
Run Code Online (Sandbox Code Playgroud)

所以,我经常从这个日志文件中检查两件事。

  1. 还给出了具有全局条件和开始时间的前几行。
  2. 最后几行,有退出状态和一些其他信息。

是否有任何快速方便的单个命令可以让我只显示文件的前几行和最后几行?

Sté*_*las 20

@rush 对于大文件使用 head + tail 更有效是正确的,但对于小文件(< 20 行),某些行可能会输出两次。

{ head; tail;} < /path/to/file
Run Code Online (Sandbox Code Playgroud)

将同样有效,但不会有上述问题。

  • @马可啊?此处仅使用 POSIX 结构。你看到哪里出了问题? (2认同)
  • @Gilles 我错过了空间:`{head; tail;} &lt; file` 在 zsh 中有效,但在 sh 中失败。`{头; tail;} &lt; file` 始终有效。对不起,噪音。 (2认同)

rus*_*ush 12

您可以使用sedawk通过一个命令来制作它。但是,您将失去速度,原因sed并且awk无论如何都需要遍历整个文件。从速度的角度来看,制作一个函数或每次都组合tail+会好得多head。如果输入是管道,这确实有不工作的缺点,但是您可以使用过程替换,以防您的 shell 支持它(请看下面的示例)。

first_last () {
    head -n 10 -- "$1"
    tail -n 10 -- "$1"
}
Run Code Online (Sandbox Code Playgroud)

并将其作为

first_last "/path/to/file_to_process"
Run Code Online (Sandbox Code Playgroud)

继续进程替换(仅 bash、zsh、ksh 之类的 shell):

first_last <( command )
Run Code Online (Sandbox Code Playgroud)

附:您甚至可以添加一个grep来检查您的“全局条件”是否存在。


Sté*_*las 9

{ head; tail; }解决方案不适用于管道(或套接字或任何其他不可查找的文件),因为head在按块读取时可能会消耗太多数据,并且无法在管道上回溯,这可能会将光标留在文件中超出tail其含义选择。

因此,您可以使用一种像 shell 一样一次读取一个字符的工具read(这里使用一个将头行和尾行的数量作为参数的函数)。

head_tail() {
  n=0
  while [ "$n" -lt "$1" ]; do
    IFS= read -r line || { printf %s "$line"; break; }
    printf '%s\n' "$line"
    n=$(($n + 1))
  done
  tail -n "${2-$1}"
}
seq 100 | head_tail 5 10
seq 20 | head_tail 5
Run Code Online (Sandbox Code Playgroud)

tail在 awk 中实现,例如:

head_tail() {
  awk -v h="$1" -v t="${2-$1}" '
    {l[NR%t]=$0}
    NR<=h
    END{
      n=NR-t+1
      if(n <= h) n = h+1
      for (;n<=NR;n++) print l[n%t]
    }'
}
Run Code Online (Sandbox Code Playgroud)

sed

head_tail() {
  sed -e "1,${1}b" -e :1 -e "$(($1+${2-$1})),\$!{N;b1" -e '}' -e 'N;D'
}
Run Code Online (Sandbox Code Playgroud)

(尽管请注意,某些sed实现对其模式空间的大小限制较低,因此对于尾线数量的大值会失败)。


nis*_*ama 6

通过GNU 的-u( ) 选项,您可以用作以下的无缓冲替代方案:--unbufferedsedsed -u 2qhead -n2

$ seq 100|(sed -u 2q;tail -n2)
1
2
99
100
Run Code Online (Sandbox Code Playgroud)

(head -n2;tail -n2)在管道中使用时,当最后几行是由 消耗的输入块的一部分时,它不会打印最后几行head

$ seq 1000|(head -n2;tail -n2)
1
2
999
1000
$ seq 100|(head -n2;tail -n2)
1
2
Run Code Online (Sandbox Code Playgroud)

如果输入是常规文件而不是管道,您可以使用(head -n2;tail -n2)

$ seq 100 >a;(head -n2;tail -n2)<a
1
2
99
100
Run Code Online (Sandbox Code Playgroud)

  • 这应该是最重要的答案!奇迹般有效! (2认同)