Awk 从多个文件中获取最后2行
我可以使用Awk 从多个文件中获取最后2行,awk,Awk,我可以使用tail命令获得多个文件的最后2行,如 $ tail -n 2 file1.txt file2.txt ==> file1.txt <== 3,2,1,1 8,8,4,4 ==> file2.txt <== B1 987 6545 C1 876 5434 $ 是否有方法仅使用awk获得上述输出 我尝试了下面这样的方法,但只适用于最后一行 $ awk ' { if(FNR==1 && NR!=1) print p,f; p=$0;f=FILE
tail
命令获得多个文件的最后2行,如
$ tail -n 2 file1.txt file2.txt
==> file1.txt <==
3,2,1,1
8,8,4,4
==> file2.txt <==
B1 987 6545
C1 876 5434
$
是否有方法仅使用awk获得上述输出
我尝试了下面这样的方法,但只适用于最后一行
$ awk ' { if(FNR==1 && NR!=1) print p,f; p=$0;f=FILENAME } END { print p,f } ' file1.txt file2.txt
8,8,4,4 file1.txt
C1 876 5434 file2.txt
$
如何将其扩展到最后2行或n行?这不是最漂亮的解决方案,但它是一个
awk
一行:
awk '{if (FNR==1 && NR!=1) {print secondLast" "prevFname ORS last" "prevFname} prevFname=FILENAME;last=$0} {secondLast=prevLine;prevLine=$0} END {print secondLast" "FILENAME ORS last" "FILENAME}' file1.txt file2.txt
请注意,随着所需行数的增加,这将变得非常笨拙。这不是最漂亮的解决方案,但它是一个
awk
所需的一行:
awk '{if (FNR==1 && NR!=1) {print secondLast" "prevFname ORS last" "prevFname} prevFname=FILENAME;last=$0} {secondLast=prevLine;prevLine=$0} END {print secondLast" "FILENAME ORS last" "FILENAME}' file1.txt file2.txt
请注意,随着所需行数的增加,这将变得非常笨拙。以下答案代表了一种兼容POSIX的解决方案,可用于任何awk。正如您从中看到的,GNU awk可以让生活变得更轻松
最后两行:最简单的两行是:
awk '(FNR==1) && f!="" { print t1,f; print t2,f }
(FNR==1) { f=FILENAME }
{ t1=t2; t2=$0 }
END { print t1, f; print t2, f}' file1 file2 file3 ...
该程序引入变量f
,该变量存储文件名和代表文件最后两行的t1
和t2
。每次我们输入一个新的非空文件(FNR==1)
或点击程序末尾时,我们都会使用这些变量进行打印
然而,这种方法有一个主要缺陷:
单行文件会产生错误的结果
最后的n
行:如果要将其扩展到最后的n
行,必须使用数组t
。此外,如果希望能够处理少于n
行的文件,则必须跟踪文件的行数(fnr
)。后一个变量fnr
将始终等于程序循环开始时前一行的fnr
而且,如果你想使用交换原则,它会变得有点混乱
awk -v n=2 '(FNR==1) && f!="" { for(i=1; i <= (fnr < n ? fnr : n); ++i) print t[i],f }
(FNR==1) { f=FILENAME }
{ fnr = FNR }
(fnr <= n) { t[fnr] = $0 }
(fnr > n) { for(i=1; i < n; ++i) t[i] = t[i+1]; t[n]=$0 }
END { for(i=1; i <= (fnr < n ? fnr : n); ++i) print t[i],f }
' file1 file2 file3 ...
awk-vn=2'(FNR=1)和&f=“{for(i=1;i下面的答案代表了一个与POSIX兼容的解决方案,它可以与任何awk一起工作。正如您从中看到的,GNU awk可以让生活更轻松一些
最后两行:最简单的两行是:
awk '(FNR==1) && f!="" { print t1,f; print t2,f }
(FNR==1) { f=FILENAME }
{ t1=t2; t2=$0 }
END { print t1, f; print t2, f}' file1 file2 file3 ...
程序引入变量f
,该变量存储文件名和t1
和t2
表示文件的最后两行。每次我们输入一个新的非空文件(FNR==1)
或点击程序末尾时,我们都使用这些变量进行打印
然而,这种方法有一个主要缺陷:
单行文件会产生错误的结果
最后的n
行:如果你想把它扩展到最后的n
行,你必须使用数组t
。此外,如果你想处理少于n
行的文件,你必须跟踪文件有多少行(fnr
).后一个变量fnr
将始终等于程序循环开始时前一行的fnr
而且,如果你想使用交换原则,它会变得有点混乱
awk -v n=2 '(FNR==1) && f!="" { for(i=1; i <= (fnr < n ? fnr : n); ++i) print t[i],f }
(FNR==1) { f=FILENAME }
{ fnr = FNR }
(fnr <= n) { t[fnr] = $0 }
(fnr > n) { for(i=1; i < n; ++i) t[i] = t[i+1]; t[n]=$0 }
END { for(i=1; i <= (fnr < n ? fnr : n); ++i) print t[i],f }
' file1 file2 file3 ...
awk-vn=2'(FNR==1)和&f!='{for(i=1;i用GNU-awk作为ENDFILE:
$ awk '{p2=p1; p1=$0} ENDFILE{print p2, FILENAME ORS p1, FILENAME }' file1 file2
3,2,1,1 file1
8,8,4,4 file1
B1 987 6545 file2
C1 876 5434 file2
一般而言,对于任意数量的n
:
$ awk -v n=2 '{p[NR%n]=$0} ENDFILE{for (i=1; i<=n; i++) print p[(NR+i)%n], FILENAME}' file1 file2
3,2,1,1 file1
8,8,4,4 file1
B1 987 6545 file2
C1 876 5434 file2
$awk-vn=2'{p[NR%n]=$0}ENDFILE{for(i=1;i使用GNU awk作为ENDFILE:
$ awk '{p2=p1; p1=$0} ENDFILE{print p2, FILENAME ORS p1, FILENAME }' file1 file2
3,2,1,1 file1
8,8,4,4 file1
B1 987 6545 file2
C1 876 5434 file2
一般而言,对于任意数量的n
:
$ awk -v n=2 '{p[NR%n]=$0} ENDFILE{for (i=1; i<=n; i++) print p[(NR+i)%n], FILENAME}' file1 file2
3,2,1,1 file1
8,8,4,4 file1
B1 987 6545 file2
C1 876 5434 file2
$awk-vn=2'{p[NR%n]=$0}ENDFILE{for(i=1;icanfor(i=1;i@stack01141006function foo(){for(i=1;i是的..非常好的研究,感谢你探索了所有的变体..ENDFILE对我不起作用..我会接受你的答案..可以for(i=1;i@stack01141006function foo(){for(i=1;我是..非常好的研究,感谢您探索所有变体..ENDFILE对我不起作用..我接受您的答案..使用ENDFILE确实让生活更轻松。这应该成为POSIX的一部分。使用ENDFILE确实让生活更轻松。这应该成为POSIX的一部分。