使用 awk 删除列中的科学记数法
Posted
技术标签:
【中文标题】使用 awk 删除列中的科学记数法【英文标题】:Use awk to remove scientific notation in a column 【发布时间】:2016-02-03 22:12:53 【问题描述】:虽然我确定这已经在某处得到了回答,但我找不到在哪里,所以如果这是重复的,我很抱歉。我们开始吧。
我有一个文件(真的,我有很多文件),其中 X、Y 和 Z 数据点由空格分隔为三列。我正在尝试使用 GNUplot 对这些进行 3d 绘制,遗憾的是,它似乎对科学记数法不太满意。现在,我可以 sed 使用 (A*10**B) 表示法而不是 (AE+B) 表示法,但 GNUplot 仍然无法识别它。
我知道我可以使用 printf "%.5f" 从科学记数法转换(我认为五位数就可以了),但我找不到如何格式化我的输入,以便我可以将其应用于多个列,或者,更好的是,如何控制每列的格式。我可以转换单个值:
echo ""|awk 'printf "%.5f", $2' k11edit.dat
但我无法让它处理多个列,甚至无法在值之间保持空格(制表符也可以;我不偏爱单个空格)。
这是我的文件的几行:
0.995 8.1584E-004 -0.17051415E+01
0.995 8.8934E-004 -0.17053282E+01
0.995 9.6284E-004 -0.17055150E+01
0.995 1.0363E-003 -0.17057018E+01
0.995 1.1098E-003 -0.17058886E+01
0.995 1.1833E-003 -0.17060754E+01
0.995 1.2568E-003 -0.17062623E+01
0.995 1.3303E-003 -0.17064493E+01
0.995 1.4038E-003 -0.17066362E+01
0.995 1.4773E-003 -0.17068232E+01
0.995 1.5508E-003 -0.17070103E+01
0.995 1.6243E-003 -0.17071973E+01
0.995 1.6978E-003 -0.17073846E+01
是的,我知道第一列在这几行中并没有改变,但它会进一步向下(文件大约 30,000 行长,所以我认为这里几行就足够了)。
你能帮帮我吗?
【问题讨论】:
编辑您的问题以显示给定示例输入的预期输出,因为不清楚您要做什么。 我的 gnuplot(4.6 版)对此表示法没有任何问题:splot 'k11edit.dat' u 1:2:3 w lp
显示您的数据点。
【参考方案1】:
没有看到您的预期输出,这是一个猜测,但这就是您想要的:
$ awk 'for (i=1;i<=NF;i++) printf "%.5f%s", $i, (i<NF?OFS:ORS)' file
0.99500 0.00082 -1.70514
0.99500 0.00089 -1.70533
0.99500 0.00096 -1.70551
0.99500 0.00104 -1.70570
0.99500 0.00111 -1.70589
0.99500 0.00118 -1.70608
0.99500 0.00126 -1.70626
0.99500 0.00133 -1.70645
0.99500 0.00140 -1.70664
0.99500 0.00148 -1.70682
0.99500 0.00155 -1.70701
0.99500 0.00162 -1.70720
0.99500 0.00170 -1.70738
如果您想为每个字段设置不同的格式:
$ awk 'BEGINsplit("%.3f %.7f %.4f",fmt)
for (i=1;i<=NF;i++) printf fmt[i]"%s", $i, (i<NF?OFS:ORS)' file
0.995 0.0008158 -1.7051
0.995 0.0008893 -1.7053
0.995 0.0009628 -1.7055
0.995 0.0010363 -1.7057
0.995 0.0011098 -1.7059
0.995 0.0011833 -1.7061
0.995 0.0012568 -1.7063
0.995 0.0013303 -1.7064
0.995 0.0014038 -1.7066
0.995 0.0014773 -1.7068
0.995 0.0015508 -1.7070
0.995 0.0016243 -1.7072
0.995 0.0016978 -1.7074
【讨论】:
我喜欢您使用?:
来拼出足以解释您的代码的分隔符。因为它是你的答案而不是我的,所以我没有发表评论。第二种形式可以写成既没有BEGIN
节也没有循环:awk 'printf "%.3f%s%7f%s%.4f%s", $1, OFS, $2, OFS, $3, ORS'
这正是我想要的。非常感谢。
@AdamKatz 是的,对于这个特定问题,我把它比必要的更笼统,所以当其他人将来查找它并且他们没有 3 个固定字段时,他们可以看到如何去做。跨度>
【参考方案2】:
有一种使用 OFMT
并强制转换为字符串的 hacky 方法。
$ awk -v OFMT='%.5f' 'print $1+"",$2+"",$3+""' file
0.99500 0.00082 -1.70514
0.99500 0.00089 -1.70533
0.99500 0.00096 -1.70551
0.99500 0.00104 -1.70570
0.99500 0.00111 -1.70589
0.99500 0.00118 -1.70608
0.99500 0.00126 -1.70626
0.99500 0.00133 -1.70645
0.99500 0.00140 -1.70664
0.99500 0.00148 -1.70682
0.99500 0.00155 -1.70701
0.99500 0.00162 -1.70720
0.99500 0.00170 -1.70738
但是,如果数字是整数,它不会转换。
【讨论】:
如果你使用$1 / 1
而不是$1 + ""
,它会将值转换为数字
可以,但需要将数字转换为字符串才能使用 OFMT。无论如何,这是一种 hack,而 printf 应该是首选方式。
无论哪种方式,整数都不起作用。您必须使用 a=0.000001; print $1+a,$2+a,$3+a
来解决这个问题(a
是 ⅒⁽ⁿ⁺¹⁾
,其中 ⁿ
是所需的精度),这会使像 0.000004 这样的值错误地向上取整。
这对整数来说不是一个好技巧。你可以改为$1+($1==int($1)?eps:0)
。以上是关于使用 awk 删除列中的科学记数法的主要内容,如果未能解决你的问题,请参考以下文章
Python使用pandas设置数据列中float数据类型的有效小数位数抑制科学计数法
如何删除 nodejs/html 中的科学记数法并仅以十进制显示?
pandas.read_csv 将字符串转换为科学记数法中的“数字”(我不想要)