如何使用gawk多次通过?

时间:2015-12-08 17:33:05

标签: awk gawk

我正在尝试使用CYGWIN中的GAWK来处理csv文件。通过1找到最大值,通过2打印匹配最大值的记录。我正在使用.awk文件作为输入。当我使用手册中的文本时,它在两次传递中都匹配。我可以使用IF形式作为解决方法,但这迫使我在每个模式匹配中使用IF,这是一种痛苦。知道我做错了吗?

这是我的.awk文件:

pass == 1
{
    print "pass1 is", pass;  
}    

pass == 2
{
if(pass == 2)
    print "pass2 is", pass;  
}    

这是我的输出(输入文件只是“你好”):

hello
pass1 is 1
pass1 is 2
hello
pass2 is 2

这是我的命令行:

gawk -F , -f test.awk pass=1 x.txt pass=2 x.txt

我很感激任何帮助。

3 个答案:

答案 0 :(得分:6)

(g)awk解决方案可能如下所示:

awk

(如有必要,请gawk替换x.txt。)
假设您要搜索文件awk -F"," 'FNR==NR {max = ( (FNR==1) || ($1 > max) ? $1 : max ); next} $1==max' x.txt x.txt 的第一列中的最大值,然后在第一列中打印具有此值的所有行,您的程序可能如下所示(感谢 Ed Morton < / em>有些提示,请参阅评论):

x.txt

6,5 2,6 5,7 6,9 的输出:

6,5
6,9

NR

这是如何工作的?变量FNR随着每条记录而不断增加,而1在读取新文件时会重置为FNR==NR。因此,{{1}}仅适用于处理的第一个文件。

答案 1 :(得分:3)

所以...... F.Knorr准确而简洁地回答了你的问题,他应该得到一个很大的绿色标记。 NR==FNR正是您正在寻找的秘密酱。

但是,这是一种不同的方法,以防万一事件被证明是有问题的。 (也许你正在从慢速驱动器,USB记忆棒,网络,DAT磁带等中读取文件。)

awk -F, '$1>m{delete l;n=0;m=$1}m==$1{l[++n]=$0}END{for(i=1;i<=n;i++)print l[i]}' inputfile

或者间隔开以便于阅读:

BEGIN {
  FS=","
}

$1 > max {
  delete list           # empty the array
  n=0                   # reset the array counter
  max=$1                # set a new max
}

max==$1 {
  list[++n]=$0          # record the line in our array
}

END {
  for(i=1;i<=n;i++) {   # print the array in order of found lines.
    print list[i]
  }
}

使用F.Knorr测试的相同输入数据,我得到相同的结果。

这里的想法是在一遍中浏览文件。我们在数组中记录与最大值匹配的每一行,如果我们遇到超过最大值的值,我们清除数组并重新开始收集行。

这种方法在CPU和内存上占主导地位(取决于数据集的大小),但是单次通过时,它可能在IO上更轻。

答案 2 :(得分:0)

这里的问题是换行符对awk很重要。

# This does what I should have done: 
pass==1 {print "pass1 is", pass;} 
pass==2 {if (pass==2) print "pass2 is", pass;}

# This is the code in my question:
# When pass == 1, do nothing
pass==1 
# On every condition, do this
    {print "pass1 is", pass;} 
# When pass == 2, do nothing
pass==2 
# On every condition, do this
    {if (pass==2) print "pass2 is", pass;}

使用pass == 1,pass == 2并不优雅,但它可以工作。