如何在awk中检测EOF?

时间:2009-10-29 21:22:42

标签: awk eof

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

11 个答案:

答案 0 :(得分:11)

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

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

例如:

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

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

awk 'END { print "Found EOF" }'

答案 1 :(得分:8)

你有两个选择,两种都很混乱。

  1. 将每个当前行的副本存储在临时变量中,然后使用END块处理它。
  2. 使用system命令在BEGIN块中运行“wc -l | getline”以获取文件中的行数,然后计算该值。
  3. 你可能需要稍微使用#2才能让它运行,但它应该有效。自从我做了任何awk以来已经有一段时间了。

答案 2 :(得分:6)

这是唯一合理的方式,按照从最好到最差的顺序做你想做的事情:

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

答案 3 :(得分:4)

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

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

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

在else之后进行文件处理。

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

   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块。

答案 4 :(得分: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
}

这个黑客的一个很酷的事情是,通过分配给$0,所有剩余的声明性模式和动作都可以工作,一行延迟了。即使您将END放在最前面,但是在最后一行上有控制权而您还没有,它就无法让它们为END工作做了别的事。

答案 5 :(得分:2)

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

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

您可以找到更多详细信息here>>

答案 6 :(得分:1)

检测参数列表中每个文件的最后一行 以下工作很好:

FNR == 1 || EOF {
  print "last line (" FILENAME "): " $0
}

答案 7 :(得分: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.'

答案 8 :(得分:0)

当你已经到达END时,awk EOF变量会告诉你。对我来说真的没什么帮助我猜

答案 9 :(得分:0)

你可以试试这个:

awk 'BEGIN{PFNR=1} FNR==PFNR{PFNR++;next} {print FILENAME,PFNR=2} END{print FILENAME}' file1 file2

答案 10 :(得分:0)

A portable solution is provided in the gawk user manual,虽然如另一个答案所述,gawk本身有BEGINFILE和ENDFILE。