打印文件夹中所有文件的第一行和最后一行

Mit*_*tch 3 shell awk

我有一大堆的是那些获得覆盖日志文件(file.log.1file.log.2等)。当我将它们从制作它们的设备复制到我的本地机器上时,我丢失了原始时间戳。所以我想把它们按时间顺序排列。问题是我不一定知道哪个是最新的,哪个是最旧的。

我希望能够做的是,如果所有日志都在一个目录中,则打印如下内容:

file: file.log.1
first line: [first line that isn't whitespace]
last line: [last line that isn't whitespace]
Run Code Online (Sandbox Code Playgroud)

我可以编写一个 python 脚本来执行此操作,但如果可能的话,我更愿意使用 linux 内置程序来执行此操作。这是 awk/sed 的工作吗?或者这对于脚本语言来说真的更好吗?如果 awk/sed 是肯定的,你将如何去做?

我通过搜索找到了这个 awk 命令,但它只接受一个文件名,并且会打印最后一行的任何内容(并且末尾可能有可变数量的空行)

awk 'NR == 1 { print }END{ print }' filename
Run Code Online (Sandbox Code Playgroud)

Cos*_*tas 6

所以我喜欢sed答案可以是

for file in file.log.*
do
   echo "file: $file"
   echo -n "first line: "
   cat "$file" | sed -n '/^\s*$/!{p;q}'
   echo -n "last line: "
   tac "$file" | sed -n '/^\s*$/!{p;q}'
done
Run Code Online (Sandbox Code Playgroud)


gle*_*man 5

一个 awk 命令:

awk -v OFS=: '
    FNR==1 {
        # the last non-blank line from the previous file
        if (line) {print filename, fnr, line}
        filename=FILENAME
        line=""
        p=0
    } 
    /^[[:blank:]]*$/ {next} 
    !p {
        # the first non-blank line
        print FILENAME, FNR, $0; p=1
    }
    {fnr=FNR; line=$0} 
    END {print filename, fnr, line}
' *
Run Code Online (Sandbox Code Playgroud)

对于每个文件,打印文件名、行号和行,以冒号分隔。

GNU awk v4 有 BEGINFILE 和 ENDFILE 模式,这大大简化了事情:

gawk -v OFS=: '
    BEGINFILE {p=0} 
    /^[[:blank:]]*$/ {next} 
    !p {print FILENAME, FNR, $0; p=1}
    {fnr=FNR; line=$0} 
    ENDFILE {print FILENAME, fnr, line}
' *
Run Code Online (Sandbox Code Playgroud)