11

有没有办法判断当前行是否是输入流的最后一行?

4

11 回答 11

13

只有在所有输入结束后,特殊END模式才会匹配。请注意,此模式不能与任何其他模式组合。

更有用的可能是getline伪函数,它重置$0到下一行并返回 1,或者在 EOF 的情况下返回 0!我认为这是你想要的。

例如:

awk '{ if(getline == 0) { print "Found EOF"} }'

如果您只处理一个文件,这将是等效的:

awk 'END { print "Found EOF" }'
于 2009-10-29T21:41:57.960 回答
9

你有两个选择,都有点乱。

  1. 将每个当前行的副本存储在临时变量中,然后使用 END 块对其进行处理。
  2. 使用系统命令在 BEGIN 块中运行“wc -l | getline”以获取文件中的行数,然后对该值进行计数。

您可能需要稍微玩一下#2 才能让它运行,但它应该可以工作。自从我做任何awk以来已经有一段时间了。

于 2009-10-29T21:40:42.250 回答
7

这些是做你想做的事的唯一明智的方法,按从最好到最坏的顺序排列:

awk 'NR==FNR{max++; next} FNR == max { print "Final line:",$0 }' file file

awk -v max="$(wc -l < file)" 'FNR == max { print "Final line:",$0 }' file

awk 'BEGIN{ while ( (getline dummy < ARGV[1]) > 0) max++; close(ARGV[1])} FNR == max { print "Final line:",$0 }' file
于 2012-12-12T20:55:25.007 回答
4

当命令行上有多个文件时,检测 EOF 不太可靠。检测文件的开头更可靠。

为此,第一个文件是特殊的,我们忽略 FNR==1。

在第一个文件之后,FNR==1 成为前一个文件的结尾。last_filename 始终具有您正在处理的文件名。

在 else 之后进行文件处理。

在 else 块和 END 块中进行 EOF 处理。

   gawk 'BEGIN{last_filename="";} \
      FNR==1{if (last_filename==""){last_filename=FILENAME;} \
      else {print "EOF: "last_filename;last_filename=FILENAME;}} \
      END{print "END: "last_filename;}' $*

对于多个文件集,else 块在 EOF 处对除最后一个文件之外的所有文件执行。最后一个文件在 END 块中执行。

对于单个文件集,不会执行 else 块,而是执行 END 块。

于 2014-02-18T21:44:39.573 回答
4

gawk实现有一个特殊的规则调用ENDFILE,它将在处理参数列表中的每个文件后触发。这有效:

awk '{line=$0} ENDFILE {print line}' files...

您可以在这里找到更多详细信息>>

于 2016-10-13T12:18:07.430 回答
2

我什至不确定如何对这个“解决方案”进行分类

{
    t = lastline
    lastline = $0
    $0 = t
}

/test/ {
    print "line <" $0 "> had a _test_"
}

END {
    # now you have "lastline", it can't be processed with the above statements
    # ...but you can work with it here
}

这个 hack 很酷的一点是,通过分配给$0,所有剩余的声明性模式和动作都有效,一行延迟。END即使您将其END放在最上面,也无法让它们为.

于 2009-11-05T01:28:07.127 回答
2

要检测参数列表中每个文件的最后一行,以下方法可以很好地工作:

FNR == 1 || EOF {
  print "last line (" FILENAME "): " $0
}
于 2010-09-09T17:49:39.717 回答
1

一种简单的方法是通过中间sed脚本运行文件,该脚本在每个非最后一行放置一个 0,在最后一行放置一个 1。

cat input_file | sed 's/^/0/;$s/0/1/' | awk '{LST=/^1/;$0=substr($0,2)}
... your awk script in which you can use LST to check for the
... last line.'
于 2011-12-06T03:17:29.740 回答
0

嗯 awkEND变量告诉您​​何时已经到达EOF. 我猜对你没有多大帮助

于 2009-10-29T21:27:05.533 回答
0

你可以试试这个:

awk 'BEGIN{PFNR=1} FNR==PFNR{PFNR++;next} {print FILENAME,PFNR=2} END{print FILENAME}' file1 file2
于 2016-02-18T08:47:49.530 回答
0

gawk 用户手册中提供了便携式解决方案,尽管如另一个答案中所述,gawk 本身具有 BEGINFILE 和 ENDFILE。

于 2018-01-02T16:55:06.973 回答