窥视下一行,但不要消耗它。

14

getline函数读取下一行并将NR计数器加1。使用getline后,awk会继续处理下一行。在大多数情况下,这是期望的行为。

在我的特殊情况下,我只需要查看下一行,根据其内容读取下一行或者需要回溯到上一行。

awk中如何回溯一行?我尝试手动设置NR计数器为NR=NR-1,但这并不起作用。或者是否有一种方法可以查看下一行而不改变NR

我需要向前看一行。简单地将该行保存在变量中并稍后引用它在这种情况下行不通。我正在尝试在awk中实现一个可读性编程工具,其中主文件可能包含许多子文件。这样的子文件以"% file:file1"之类的行开头。如果达到缩进较低的另一行或带有"% file:file2"之类的行,则到达此类文件的结尾。

当我已经使用getline读取了这一行时,所有匹配/% file:/的行的规则集不会被使用。这就是为什么我想将NR重置为上一行,然后awk将再次读取与/% file:/匹配的行并执行相应的规则。


1
我开发了一种名为TXR的文本处理语言,它具有基于模式匹配的隐式回溯功能,支持基于行(“垂直”)和字符(“水平”)的匹配模式。前瞻深度可以是任意数量的字符或行。TXR几乎是处理文学编程符号的理想工具。很难给出一个直接相关的例子;你能发布完整的文学符号规范吗? - Kaz
3个回答

13

这可能接近你要寻找的内容,而且不会像用 sed 的解决方案那样昂贵,因为 AWK 维护一个指向通过 getline 打开的文件的指针。

awk 'FNR == 1 {
         getline nextline < FILENAME
     }
     {
         getline nextline < FILENAME;
         print "currentline is:", $0;
         print "nextline is:   ", nextline
     }' input file

第一个块读取第一行并将其浪费。

使用这种形式的getline不会设置任何变量,如NRFNRNF$0。它只设置您提供的变量(在此示例中为nextline)。

有关更多信息,请参见此处


遗憾的是,这似乎是GNU awk特定的。 - 0xC0000022L
我使用以下命令检查了您的方法:for i in {1..10} ; do echo $i ; done > tesxt2.txt && awk --posix '{getline var < FILENAME ; print var,$i}' tesxt2.txt && rm tesxt2.txt。不幸的是,getline无法显示下一行。这是因为缺少FNR == 1吗? - Alexander Cska
@DennisWilliamson,感谢您的快速回复。不幸的是,print var,$i显示相同的变量(1,1,2,2等)。应该是print var,$0,但在这两种情况下,输出都没有捕获“新旧”行。 - Alexander Cska
@AlexanderCska:问题在于你的脚本中,awk 正在打印 var,$i,而且 i 没有被设置。如果设置了,它将会打印 field i,因为有美元符号。它应该打印 var,$0。只是碰巧未设置的 i 被解释为零,所以它似乎做了你想要的事情。但你测试的主要问题是没有包括我答案中的第一个块 (FNR == 1 { ... })。 - Dennis Williamson

1

这是一种有点取巧且相当昂贵的方法,但对于小文件确实可以提前查看:

cmd="sed -n " NR + 1 "p " FILENAME; cmd | getline nextline

这将获取 NR 的当前值,并使用 sed 从输入文件中提取行 NR + 1。这是昂贵的,因为每次进行前瞻时 sed 将读取整个文件(您可以通过在 sed 中添加一个 'q' 命令来稍微减轻它)。变量 nextline 将设置为文件的下一行,在最后一行为空。


0
只需创建一个变量来存储你的最后一行。
BEGIN { last = "" }

然后在下一次迭代中检查并设置最后一行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接