如何在gawk中使用多个通行证?
我正在尝试使用CYGWIN的GAWK来处理csv文件。Pass 1查找最大值,Pass 2打印与最大值匹配的记录。我正在使用一个.awk文件作为输入。当我使用手册中的文本时,它在两个过程中都匹配。我可以使用IF表单作为解决方法,但这迫使我在每个模式匹配中使用IF,这是一种痛苦。知道我做错了什么吗 这是我的.awk文件:如何在gawk中使用多个通行证?,awk,gawk,Awk,Gawk,我正在尝试使用CYGWIN的GAWK来处理csv文件。Pass 1查找最大值,Pass 2打印与最大值匹配的记录。我正在使用一个.awk文件作为输入。当我使用手册中的文本时,它在两个过程中都匹配。我可以使用IF表单作为解决方法,但这迫使我在每个模式匹配中使用IF,这是一种痛苦。知道我做错了什么吗 这是我的.awk文件: pass == 1 { print "pass1 is", pass; } pass == 2 { if(pass == 2) print "pas
pass == 1
{
print "pass1 is", pass;
}
pass == 2
{
if(pass == 2)
print "pass2 is", pass;
}
这是我的输出(输入文件只是“hello”):
这是我的命令行:
gawk -F , -f test.awk pass=1 x.txt pass=2 x.txt
非常感谢您的帮助。一个(g)awk解决方案可能是这样的:
awk 'FNR == NR{print "1st pass"; next}
{print "second pass"}' x.txt x.txt
(如有必要,请将awk
替换为gawk
。比方说,您希望在文件
x.txt
的第一列中搜索最大值,然后打印第一列中具有该值的所有行,您的程序可能如下所示(感谢Ed Morton提供的一些提示,请参阅注释):
x.txt的输出:
6,5
2,6
5,7
6,9
是
这是如何工作的?变量NR
随着每条记录的增加而不断增加,而FNR
在读取新文件时被重置为1
。因此,FNR==NR
仅对处理的第一个文件有效。因此……F.Knorr准确而简洁地回答了你的问题,他应该得到一个绿色的大复选标记。NR==FNR
正是您要寻找的秘方
但这里有一种不同的方法,以防多通道的事情被证明是有问题的。(也许你是从慢速驱动器、U盘、网络、DAT磁带等读取文件。)
awk-F,'$1>m{delete l;n=0;m=$1}m==1{l[++n]=$0}END{for(i=1;i这里的问题是换行符对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并没有那么优雅,但它可以工作。@MarkSetchell:你是对的,括号是没有必要的。因此,我更新了我的答案。然而,对于像我这样习惯于Java/C的人来说……包含条件的括号更为熟悉。(条件){code block}
。该脚本中没有特定于gawk的内容。为了避免要求max>=0,并使脚本可移植到所有AWK(某些AWK在某些情况下使用未细化的三元表达式会失败)并且更易于阅读,请将测试更改为FNR==NR{max=((FNR==1)| |($1>max)$1:max);下一步}
。任何时候进行最小值或最大值计算时,请使用读取的第一个值进行种子设定,不要使用诸如零之类的随机值进行种子设定。您可以而且应该删除{print$0}
,因为当条件为真时,这是默认操作。@EdMorton:谢谢您的评论。我已相应地修改了我的答案(也为此向您表示感谢)谢谢你的帮助。我找到了答案。请看下面我的答案。很好,但按照惯例,正如每个awk函数所创建的那样,awk数组(以及字符串字符位置和字段号)从1开始,而不是从0开始,所以只需调整到list[++n]=$0(i=1;我非常感谢你指出这一点。在我的awk生涯中,我从未想到过这一点。我已经调整了这个答案,但是……现在我必须梳理一小部分其他脚本来进行类似的调整。哇!:-P@EdMorton-哦,最后for循环中的条件也需要更改为iYeah It当我读到你上面的第一条评论时,但那时编辑我的评论已经太晚了,我想你也会马上发现它。@EdMorton,很抱歉让你回到这一点,但我注意到,声明“通常,数组中的索引必须是非负整数。例如,索引0指定数组中的第一个元素。“这似乎是“nawk”文档中数组简介的直接转录。您是否有任何关于在1开始数组的约定的参考资料?仅供参考GNU awk有一个名为argid
的变量,它使您的pass
变量冗余。
6,5
2,6
5,7
6,9
6,5
6,9
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]
}
}
# 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;}