如何在awk中检测EOF?

问题描述 投票:9回答:11

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

awk eof
11个回答
8
投票

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

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

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


0
投票

你可以试试这个:

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

0
投票

A portable solution is provided in the gawk user manual,虽然在另一个答案中提到,gawk本身有BEGINFILE和ENDFILE。


11
投票

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

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

例如:

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

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

awk 'END { print "Found EOF" }'

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

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


2
投票

I'm not even sure how to categorize this "solution"

{
    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放在最上面,但是你确实控制了最后一行而你还没有做任何其他事情。


2
投票

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

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

你可以找到更多细节here>>


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.'

1
投票

要检测参数列表中每个文件的最后一行,以下方法很有效:

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

0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.