【发布时间】:2016-04-04 21:35:15
【问题描述】:
我需要一个脚本来打印文本文件的最后 n 行。文本文件名和行数可以变化,我只想调用脚本来打印任何文本文件的最后 n 行。我知道前 n 行我可以使用 NR
【问题讨论】:
标签: awk
我需要一个脚本来打印文本文件的最后 n 行。文本文件名和行数可以变化,我只想调用脚本来打印任何文本文件的最后 n 行。我知道前 n 行我可以使用 NR
【问题讨论】:
标签: awk
有一个专门用于此目的的 unix 工具,称为 tail。要获取文件的最后 100 行,您可以使用 tail -n 100 file,然后直接使用输出或将其通过管道传输到 awk 等其他程序。
【讨论】:
要在 awk 中本地执行此操作,您必须记住所看到的行:
awk -v n=10 '
{line[NR]=$0}
END {for (i=NR-(n-1); i<=NR; i++) print line[i]}
' file
为了节省内存,我们不需要记住整个文件;使用
{line[NR]=$0; if (NR>n) delete line[NR-n]}
不过倒转文件比较简单,打印前 n 行,然后重新倒转输出
tac file | awk -v n=10 'NR <= n' | tac
但是使用tail 比所有这些都简单得多
【讨论】:
作为练习,还有另一个版本的交易空间与时间来实现相同的效果
$ awk -v n=10 'NR==FNR{a=NR;next} FNR>(a-n)' file{,}
首先扫描文件以获取行数,然后用于第二次过滤最后 n 行。
【讨论】:
$ cat file
1
2
3
4
$ cat tst.awk
{ rec[NR % n] = $0 }
END {
for (i=NR+1+(n<NR?0:n-NR); i<=(NR+n); i++) {
print rec[i % n]
}
}
$ awk -v n=2 -f tst.awk file
3
4
设置i 的起始值时的复杂性是为了适应您要求打印的记录多于文件中现有记录的情况,例如:
$ awk -v n=6 -f tst.awk file
1
2
3
4
【讨论】:
试试这个脚本:
{
lines[(i=(++i%n))]=$0;
}
END {
if (NR>=n) {
linessize=n;
} else {
linessize=NR;
i=0;
}
for(j=1;j<=linessize;j++) {
print lines[(i+j)%n];
}
}
文件只解析一次。
n 个元素的数组only 用于缓冲读取的行。
测试:
$ printf "one line\n2nd line\n" | ./tail-awk.awk -f script.awk -v n=10
one line
2nd line
$ ./tail-awk.awk -f script.awk -v n=10 <(man bash)
attempted. When a process is stopped, the shell immediately executes the next command in the sequence. It suffices to
place the sequence of commands between parentheses to force it into a subshell, which may be stopped as a unit.
Array variables may not (yet) be exported.
There may be only one active coprocess at a time.
GNU Bash-4.1 2009 December 29 BASH(1)
$ ./tail-awk.awk -f script.awk -v n=5 /etc/apt/sources.list
deb http://archive.debian.org/debian-archive hamm main
deb ftp://ftp.debian.org/debian squeeze contrib
$
【讨论】: