2017-08-16 29 views
2

我有一个使用AWK非常令人沮丧的问题,并且一直无法在这里找到解决方案。 它(应该是!)很简单:AWK:试图在列中查找值的实例; awk返回南的实例以及值

我有一个包含3列的文本文件'myfile.txt'。内容是:

-101.358 80.775 3 
-100.187 80.850 2 
-98.019 80.976 NaN 
-96.476 81.0566 NaN 

所有我想要做的就是找回其中列3 = 3。所以我做例子:

awk '{if ($3 == 3) print $1, $2, $3}' myfile.txt

返回:

-101.358 80.775 3 
-98.019 80.976 NaN 
-96.476 81.0566 NaN 

出于某种原因,正在返回NaN以及我正在寻找的3个。 我得到了相同的结果:

awk '$3 == 3 {print $1, $2, $3}' myfile.txt

返回:

-101.358 80.775 3 
-98.019 80.976 NaN 
-96.476 81.0566 NaN 

我可以做克服的问题:

awk '{if ($3 == 3 && $3 != nan) print $1, $2, $3}' myfile.txt

返回:

-101.358 80.775 3 

但是,每次使用awk在我的文件中查找某些值的实例时,必须包含此额外条件是一件痛苦的事情。

请帮忙! 我运行版本20070501.

非常感谢

+1

不能在这里转载。 'awk'$ 3 == 3''给出你想要的。 – Kent

+0

我通过在同事建议中安装gawk解决了这个问题。我相信我使用的是旧版本的awk。谢谢 – izzyrizzy

+0

在任何情况下,'awk'$ 3 == 3'文件'是你想要的命令。其他一切都是多余的,因为打印整行是awk的默认操作。 – hek2mgl

回答

1

的问题是,你正在试图做的数值比较与不使用支持的情况下独立nan符号一个awk数字值(可能inf),并获得不良结果。

通常,所有的awk值都是数字或字符串。 nan是特殊的(在某些awk中),因为awk或它使用的底层C原语必须决定如何处理它。

当比较任何数字nan最明智的选择是总是导致“失败”,因为没有数字可以等于(也不比小于也不更大)nan但显然有些awk的供应商决定不这样做,作为你发现了。我个人会认为这是一个错误,但我不太了解数字理论或围绕nan的使用标准的历史记录来说明是否是。耸肩。

如果没有--posix标志gawk会将nan视为字符串,但会将+nan-nan视为“特殊”数值。使用--posix gawk会将nan视为底层C基元决定它在您所运行的系统上。这些决定是为了支持历史计划,并且会因系统而异。

所以,尽管你觉得不--posix GAWK现在是为你工作,因为$3==3是假的,当输入为NaN,它实际上不是,它在字符串NaN只是转换为0的数值比较。

您的问题的便携式解决方案是 - 不要这样做。如果输入的数据可以包含nan当时的编写代码不过来处理他们,你希望他们处理,如:

$ awk '$3!="NaN" && $3==3' file 
-101.358 80.775 3 

gawk --posix会做你想做的与您现有的数据:

$ gawk '$3==3' file 
-101.358 80.775 3 

$ gawk --posix '$3==3' file 
-101.358 80.775 3 

$ echo '1 2 NaN' | gawk '$3+0==0' 
1 2 NaN 

$ echo '1 2 NaN' | gawk --posix '$3+0==0' 
$ 

和WRT能够在nans进行算术和有结果也是一个nan在您的意见,也需要gawk --posix与您的数据中提到:

$ gawk '{print $2 - $3}' file 
77.775 
78.85 
80.976 
81.0566 

$ gawk --posix '{print $2 - $3}' file 
77.775 
78.85 
nan 
nan 

所以它听起来像gawk --posix将提供所需的所有行为,你需要从你有的数据,但要小心通常的截断规则转换字符串看起来像数字到数字适用所以如果你有一个输入字符串开始任何awk考虑了nan那么它会得到一个数字语境中时,而不是转换为零映射到nan

$ echo 'nanny' | gawk '{ print $1 + 0 }' 
0 

$ echo '+nannny' | gawk '{ print $1 + 0 }' 
nan 

$ echo 'nanny' | gawk --posix '{ print $1 + 0 }' 
nan 

另外要注意,在POSIX模式下使用GAWK去掉所有的它是非常有用的扩展名如gensub()所以更好的方法可能是在nan的前面加上+ s,这样gawk就可以将它们识别为nan•不用要求--posix障碍和不思考你的意思nan当你写nanny(见上文):

$ echo 'nan' | gawk '{print ($1+0==0)}' 
1 

$ echo 'nan' | gawk --posix '{print ($1+0==0)}' 
0 

$ echo '+nan' | gawk '{print ($1+0==0)}' 
0 

$ echo '+nan' | gawk --posix '{print ($1+0==0)}' 
0 

$ echo '+nan' | gawk '{print ($1+0==0), gensub(/foo/,"bar",1)}' 
0 +nan 

$ echo '+nan' | gawk --posix '{print ($1+0==0), gensub(/foo/,"bar",1)}' 
gawk: cmd. line:1: warning: regexp constant for parameter #1 yields boolean value 
gawk: cmd. line:1: (FILENAME=- FNR=1) fatal: function `gensub' not defined 

$ cat file 
-101.358 80.775 3 
-100.187 80.850 2 
-98.019 80.976 +NaN 
-96.476 81.0566 +NaN 

$ gawk '{print $2 - $3}' file 
77.775 
78.85 
nan 
nan 

因此,在总结 - 而gawk --posix将与您当前的数据工作,我建议你改变你的数据使用+NaN而不是NaN,所以它在没有--posix的gawk中工作,因此您可以访问许多令人难以置信的有用扩展,并且您不会意外获得以nan开头的字符串(例如nanny)转换为nan

+1

感谢您的详细解答 – Thor

+1

感谢您的详细回复Ed - 非常有帮助。看起来posix确实能解决我的问题。当你在我原来的问题中说错字时,我已经纠正了它。为此而道歉! – izzyrizzy

+0

不客气。是的,今天添加'--posix'将与你的数据一起工作,但是我建议你改变你的数据来使用'+ NaN'而不是'NaN',所以它在没有'--posix'的情况下工作,所以你可以访问gawks许多非常有用的扩展。 –