我正在尝试操作一个包含科学记数法数字的文件,但没有符号e
,即1.2e+3
写为1.2+3
.
我想到的最简单的事情awk
就是替换+
为e+
,使用该gsub
函数并在新文件中进行计算。对于负值情况也是如此。因此可以使用以下命令完成简单的修复
awk '{gsub("+", "e+", $1); print $1, $2, $3, $4, $5}' file_in
并在所有列中执行相同的操作。
然而,该文件还包含负数,这使事情变得更加复杂。示例文件如下所示
1.056000+0 5.000000-1 2.454400-3 2.914800-2 8.141500-6
2.043430+1 5.000000-1 2.750500-3 2.698100-2-2.034300-4
3.829842+1 5.000000-1 1.969923-2 2.211364-2 9.499900-6
4.168521+1 5.000000-1 1.601262-2 3.030919-2-3.372000-6
6.661784+1 5.000000-1 5.250575-2 3.443669-2 2.585500-5
7.278104+1 5.000000-1 2.137055-2 2.601701-2 8.999800-5
9.077287+1 5.000000-1 1.320498-2 2.961020-2-1.011600-5
9.248130+1 5.000000-1 3.069610-3 2.786329-2-6.317000-5
1.049935+2 5.000000-1 4.218794-2 3.321955-2-5.097000-6
1.216283+2 5.000000-1 1.432105-2 3.077165-2 4.300300-5
关于如何使用这样的文件进行操作和计算有什么想法吗?
答案1
这个输出正确吗?
1.056000e+0 5.000000e-1 2.454400e-3 2.914800e-2 8.141500e-6
2.043430e+1 5.000000e-1 2.750500e-3 2.698100e-2-2.034300e-4
3.829842e+1 5.000000e-1 1.969923e-2 2.211364e-2 9.499900e-6
4.168521e+1 5.000000e-1 1.601262e-2 3.030919e-2-3.372000e-6
6.661784e+1 5.000000e-1 5.250575e-2 3.443669e-2 2.585500e-5
7.278104e+1 5.000000e-1 2.137055e-2 2.601701e-2 8.999800e-5
9.077287e+1 5.000000e-1 1.320498e-2 2.961020e-2-1.011600e-5
9.248130e+1 5.000000e-1 3.069610e-3 2.786329e-2-6.317000e-5
1.049935e+2 5.000000e-1 4.218794e-2 3.321955e-2-5.097000e-6
1.216283e+2 5.000000e-1 1.432105e-2 3.077165e-2 4.300300e-5
代码:
perl -lne 's/(\.\d+)(\+|\-)/\1e\2/g; print' sample
解释:
-lne
处理行结尾,处理每个输入行,执行后面的代码s/(\.\d+)(\+|\-)/\1e\2/g
:- 代替 (
s
) (.\d+)(\+|\-)
找到两组(一个点和数字)和(一个加号或减号)\1e\2
用第一组替换它们,然后e
用第二组替换它们g
全局 - 不要在每行的第一个替换处停止,而是处理所有可能的命中
- 代替 (
print
打印该行sample
输入文件
如果缺少的话,这个会增加空间。事实上,它无论如何都会在数字之间留出空格。 IE。如果在某种情况下有两个空格,则输出中将只有一个。
perl -lne 's/(\.\d+)(\+|\-)(\d+)(\s*)/\1e\2\3 /g; print' sample
大部分内容与上一篇类似。新的东西是(\d+)
组nr 3和(\s*)
组nr 4。*
这里的意思是可选的。在替换中\4
使用 no。而是有一个空间。
输出是这样的:
1.056000e+0 5.000000e-1 2.454400e-3 2.914800e-2 8.141500e-6
2.043430e+1 5.000000e-1 2.750500e-3 2.698100e-2 -2.034300e-4
3.829842e+1 5.000000e-1 1.969923e-2 2.211364e-2 9.499900e-6
4.168521e+1 5.000000e-1 1.601262e-2 3.030919e-2 -3.372000e-6
6.661784e+1 5.000000e-1 5.250575e-2 3.443669e-2 2.585500e-5
7.278104e+1 5.000000e-1 2.137055e-2 2.601701e-2 8.999800e-5
9.077287e+1 5.000000e-1 1.320498e-2 2.961020e-2 -1.011600e-5
9.248130e+1 5.000000e-1 3.069610e-3 2.786329e-2 -6.317000e-5
1.049935e+2 5.000000e-1 4.218794e-2 3.321955e-2 -5.097000e-6
1.216283e+2 5.000000e-1 1.432105e-2 3.077165e-2 4.300300e-5
答案2
您也可以使用sed
,例如:
<infile sed -E 's/([0-9])([+-])([0-9])/\1e\2\3/g' | awk '{ print $1 + 0 }'
然而,这没有考虑到 OP 列表中的列有时是不分隔的。这是一个具有适当精度的解决方法:
<infile sed -E 's/.{11}/& /g' |
sed -E 's/([0-9])([+-])/\1e\2/g' |
gawk '{ print $1 + 0 }' OFMT='%.7g'
输出:
1.056
20.4343
38.29842
41.68521
66.61784
72.78104
90.77287
92.4813
104.9935
121.6283