如何用awk处理3个文件?

时间:2014-07-14 15:01:05

标签: awk gawk nawk

好的,所以花了2天后,我无法解决它,现在我几乎没时间了。这可能是一个非常愚蠢的问题,所以请耐心等待。我的awk脚本做了这样的事情:

BEGIN{ n=50; i=n; }
FNR==NR {
            # Read file-1, which has just 1 column
            ids[$1]=int(i++/n);
            next
        }
        {
            # Read file-2 which has 4 columns
            # Do something
            next
        }
 END {...}

工作正常。但现在我想将它扩展为3个文件。让我们说,不是硬编码" n"的值,我需要读取属性文件并设置" n"的值。从那以后。我找到了this question,并尝试过这样的事情:

BEGIN{ n=0; i=0; }
FNR==NR {
            # Block A
            # Try to read file-0
            next
        }
        {
            # Block B
            # Read file-1, which has just 1 column
            next
        }
        {
            # Block C
            # Read file-2 which has 4 columns
            # Do something
            next
        }
 END {...}

但它不起作用。块A是为file-0执行的,我能够从属性文件中读取属性。但是对于文件-1和文件-2都执行块B.并且块C永远不会被执行。

有人可以帮我解决这个问题吗?我之前从未使用过awk,语法非常混乱。此外,如果有人可以解释awk如何从不同的文件中读取输入,那将非常有用。

如果我需要在问题中添加更多详细信息,请与我们联系。

3 个答案:

答案 0 :(得分:8)

如果你有傻瓜,只需测试ARGIND:

awk '
ARGIND == 1 { do file 1 stuff; next }
ARGIND == 2 { do file 2 stuff; next }
' file1 file2

如果你没有傻瓜,那就去吧。

在其他问题中,您可以只测试文件名:

awk '
FILENAME == ARGV[1] { do file 1 stuff; next }
FILENAME == ARGV[2] { do file 2 stuff; next }
' file1 file2

只有在你想要解析同一个文件两次时才会失败,如果是这种情况你需要添加文件被打开次数的计数。

答案 1 :(得分:6)

更新:只要所有输入文件都是非空下面的解决方案就可以正常工作,但会看到@Ed Morton's answer为了更简单,更健壮的方式添加特定于文件的处理

然而,这个答案仍然提供了一些希望有用的解释,说明了一些awk基础知识以及为什么OP的方法不起作用。


请尝试以下操作(请注意,我已将索引设为 1 ,因为这是awk的工作方式):

awk '

 # Increment the current-file index, if a new file is being processed.
 FNR == 1 { ++fIndex }

 # Process current line if from 1st file.
 fIndex == 1 {
    print "file 1: " FILENAME
    next
 }

 # Process current line if from 2nd file.
 fIndex == 2 {
    print "file 2: " FILENAME
    next
 }

 # Process current line (from all remaining files).
 {
    print "file " fIndex ": " FILENAME
 }

' file-1 file-2 file-3
  • 只要新输入文件开始处理(FNR==1包含输入文件相对行号),模式FNR就为真。
  • 每次新文件开始处理时,fIndex都会递增,从而反映当前输入文件的从1开始的索引。 提示@twalberg's helpful answer

    • 请注意,数字上下文中使用的未初始化awk变量默认为0,因此无需初始化fIndex(除非您需要不同的起始值)。
  • 然后可以使用fIndex == 1之类的模式来执行仅来自特定输入文件的行的块(假设块以next结尾)。
  • 然后对没有文件特定块的所有输入文件执行最后一个块(上面)。

至于为什么你的方法不起作用

  • 对于来自所有输入文件的行,您的第2和第3个块可能无条件执行 ,因为它们之前没有模式(条件)。

  • 因此,为所有后续输入文件中的行输入了第2个块,而其next语句则阻止第3个块到达

潜在的误解

  • 也许您认为每个块都可以作为处理单个输入文件的循环。这不是awk的工作原理。相反,整个awk程序在循环中处理,每次迭代处理单个输入行,从文件1的所有行开始,然后从文件开始2,......

  • awk程序可以包含任意数量的块(通常以模式开头),并且它们是否为当前输入行执行仅受模式评估为真的控制;如果没有模式,则无条件地执行 (跨输入文件)。但是,正如您已经发现的那样,块中的next可用于跳过后续块(模式块对)。

答案 2 :(得分:1)

也许您需要考虑添加一些额外的结构:

BEGIN { file_number=1 }
FNR==1 { ++file_number }
file_number==3 && /something_else/ { ...}