我有一个管道分隔的Feed文件,其中包含多个字段。由于我只需要一些,我想到使用awk
来捕获它们以用于我的测试目的。但是,我注意到,如果我使用 printf
, "%d"
会更改该值。如果我使用 "%s"
,它可以正常工作。
[jaypal:~/Temp] cat temp
302610004125074|19769904399993903|30|15|2012-01-13 17:20:02.346000|2012-01-13 17:20:03.307000|E072AE4B|587244|316|13|GSM|1|SUCC|0|1|255|2|2|0|213|2|0|6|0|0|0|0|0|10|16473840051|30|302610|235|250|0|7|0|0|0|0|0|10|54320058002|906|722310|2|0||0|BELL MOBILITY CELLULAR, INC|BELL MOBILITY CELLULAR, INC|Bell Mobility|AMX ARGENTINA SA.|Claro aka CTI Movil|CAN|ARG|
我有兴趣捕获 second column
19769904399993903
。
[jaypal:~/Temp] awk -F"|" '{printf ("%d\n",$2)}' temp
19769904399993904 # Value is changed
但是,以下两个测试工作正常 -
[jaypal:~/Temp] awk -F"|" '{printf ("%s\n",$2)}' temp
19769904399993903 # Value remains same
[jaypal:~/Temp] awk -F"|" '{print $2}' temp
19769904399993903 # Value remains same
这是 "%d"
无法处理长整数的限制。如果是这样的话,为什么会在数字中加一个而不是截断呢?
我尝试使用 BSD
和 GNU
版本的 awk
。
[jaypal:~/Temp] gawk --version
GNU Awk 4.0.0
Copyright (C) 1989, 1991-2011 Free Software Foundation.
[jaypal:~/Temp] awk --version
awk version 20070501
答案 0 :(得分:8)
从GNU awk 4.1开始,您可以使用--bignum
或-M
$ awk 'BEGIN {print 19769904399993903}'
19769904399993904
$ awk --bignum 'BEGIN {print 19769904399993903}'
19769904399993903
答案 1 :(得分:5)
我认为这种情况下的基础数字格式是IEEE双精度格式。因此,更改的值是浮点精度错误的结果。如果实际上有必要将大值视为数值并保持准确的精度,那么使用Perl,Ruby或Python等具有功能(可能通过扩展)来处理任意精度算术的东西可能更好。
答案 2 :(得分:4)
UPDATE :最新版本的GNU awk支持任意精度算术。有关详细信息,请参阅GNU awk manual。
原始帖子内容: XMLgawk支持对浮点数进行任意精度算术。 因此,如果安装 xgawk 是一个选项:
zsh-4.3.11[drado]% awk --version |head -1; xgawk --version | head -1
GNU Awk 4.0.0
Extensible GNU Awk 3.1.6 (build 20080101) with dynamic loading, and with statically-linked extensions
zsh-4.3.11[drado]% awk 'BEGIN {
x=665857
y=470832
print x^4 - 4 * y^4 - 4 * y^2
}'
11885568
zsh-4.3.11[drado]% xgawk -lmpfr 'BEGIN {
MPFR_PRECISION = 80
x=665857
y=470832
print mpfr_sub(mpfr_sub(mpfr_pow(x, 4), mpfr_mul(4, mpfr_pow(y, 4))), 4 * y^2)
}'
1.0000000000000000000000000
答案 3 :(得分:2)
@Mark Wilkins和@Dennis Williamson已经部分回答了这个问题,但我发现最大的64位整数可以处理而不会丢失精度是2 ^ 53。 例如awk的参考页面 http://www.gnu.org/software/gawk/manual/gawk.html#Integer-Programming
(对不起,如果我的回答太旧了。想想我还是会为下一个人分享,就像他们花了太多时间一样)
答案 4 :(得分:1)
你遇到了Awk's Floating Point Representation Issues。我认为你不能在awk框架中找到解决方法来准确地对大数字进行算术运算。
我能想到的只有可能(和原始)的方法是将巨大的数字分解成更小的块,执行数学并再次加入它们或更好地使用比其更强大的Perl / PHP / TCL / bsh等脚本语言AWK。
答案 5 :(得分:0)
在Solaris 11上使用nawk,我通过向末尾添加(连接)null将数字转换为字符串,然后使用%15s
作为格式字符串:
printf("%15s\n", bignum "")