awk中如何检测EOF?

发布于 2024-08-09 07:08:39 字数 29 浏览 6 评论 0原文

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

Is there a way to determine whether the current line is the last line of the input stream?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

很酷不放纵 2024-08-16 07:08:40

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

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

更多详细信息您可以在此处>>找到

gawk implementation has special rule called ENDFILE which will be triggered after processing every file in argument list. This works:

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

more details you can find here>>

め七分饶幸 2024-08-16 07:08:40

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

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

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

在其他之后进行文件处理。

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

Detecting the EOF is not too reliable when multiple files are on the command line. Detecting the start of the file is more reliable.

To do this, the first file is special and we ignore the FNR==1.

After the first file then FNR==1 becomes the end of the previous file. last_filename always has the filename that you are processing.

Do your file processing after the else.

Do your EOF processing inside the else block, AND in the END block.

   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;}' $*

For multiple file sets, the else block executes at EOF for all but the last file. The last file is executed in the END block.

For single file sets, the else block doesn't get executed, and the END block is executed.

尸血腥色 2024-08-16 07:08:40

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

{
    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 工作,但您确实可以控制最后一个线,并且您没有对其执行任何其他操作。

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
}

The cool thing about this hack is that by assigning to $0, all the remaining declarative patterns and actions work, one line delayed. You can't get them to work for the END, even if you put the END on top, but you do have control on the last line and you haven't done anything else to it.

思慕 2024-08-16 07:08:40

一种简单的方法是通过中间 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.'

One easy way is to run the file via an intermediate sed script, that places a 0 on every non last line, and a 1 on the last one.

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.'
被翻牌 2024-08-16 07:08:40

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

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

To detect the last line of each file in the argument list
the following works nicely:

FNR == 1 || EOF {
  print "last line (" FILENAME "): " $0
}
黑寡妇 2024-08-16 07:08:40

嗯,awk END 变量会告诉您何时已经到达 EOF。我想对你来说并没有多大帮助

Hmm the awk END variable tells when you have already reached the EOF. Isn't really much of help to you I guess

離人涙 2024-08-16 07:08:40

你可以试试这个:

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

you can try this:

awk 'BEGIN{PFNR=1} FNR==PFNR{PFNR++;next} {print FILENAME,PFNR=2} END{print FILENAME}' file1 file2
歌入人心 2024-08-16 07:08:40

gawk 用户手册中提供了便携式解决方案,虽然在另一个答案中提到,gawk本身有BEGINFILE和ENDFILE。

A portable solution is provided in the gawk user manual, although as mentioned in another answer, gawk itself has BEGINFILE and ENDFILE.

孤蝉 2024-08-16 07:08:39

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

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

These are the only sensible ways to do what you want, in order of best to worst:

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
近箐 2024-08-16 07:08:39

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

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

例如:

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

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

awk 'END { print "Found EOF" }'

The special END pattern will match only after the end of all input. Note that this pattern can't be combined with any other pattern.

More useful is probably the getline pseudo-function which resets $0 to the next line and return 1, or in case of EOF return 0! Which I think is what you want.

For example:

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

If you are only processing one file, this would be equivalent:

awk 'END { print "Found EOF" }'
单身情人 2024-08-16 07:08:39

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

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

您可能需要稍微尝试一下#2 才能让它运行,但它应该可以工作。我已经有一段时间没有做过 awk 了。

You've got two options, both kind of messy.

  1. Store a copy of every current line in a temp variable, and then use the END block to process it.
  2. Use the system command to run "wc -l | getline" in the BEGIN block to get the number of lines in the file, and then count up the that value.

You might have to play with #2 a little to get it to run, but it should work. Its been a while since I've done any awk.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文