![通过文本文件转换小数位数](https://linux22.com/image/1054026/%E9%80%9A%E8%BF%87%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E8%BD%AC%E6%8D%A2%E5%B0%8F%E6%95%B0%E4%BD%8D%E6%95%B0.png)
这个问题的解决方案可能围绕 perl、sed 或 awk,不幸的是我对其中任何一个都不熟悉。
我的目的是将计算机生成的文本文件转换为更易于人类阅读的属性。为此,我希望将所有十进制数字超过 10 位的数字处理为大约 2。这应该与它们周围的关键字无关。
示例日志文件:
[General]
Date=2016-01-20
Timestamp=2016-01-20T12:30:00
[Dewpoint]
Low=-17.7041803458378
LTime=14:55
High=-13.1057525836829
HTime=13:42
[Solar]
SunshineHours=4.78333333333332
SunshineHoursToMidnight=0.750000000000001
期望输出:
[General]
Date=2016-01-20
Timestamp=2016-01-20T12:30:00
[Dewpoint]
Low=-17.70
LTime=14:55
High=-13.11
HTime=13:42
[Solar]
SunshineHours=4.78
SunshineHoursToMidnight=0.75
这里不需要四舍五入,截断就足以满足我的需要。
如果没有 RTWFM 我该如何实现这一目标?
答案1
awk -F"=" -v OFS="=" '
NF == 2 && $2 ~ /^-?[0-9]*\.[0-9]+$/ {$2 = sprintf("%.2f", $2)}
{print}
' file.log
用作=
字段分隔符。对于包含 2 个字段且第 2 个字段为浮点数的行,重新格式化第 2 个字段。
输出样本数据为
[General]
Date=2016-01-20
Timestamp=2016-01-20T12:30:00
[Dewpoint]
Low=-17.70
LTime=14:55
High=-13.11
HTime=13:42
[Solar]
SunshineHours=4.78
SunshineHoursToMidnight=0.75
答案2
也许是这样的:
perl -pe 's/(?<==)[-+]?[0-9]*\.?[0-9]+(!:)/sprintf("%.2f",$&)/e' log
=
它以精度 2 重新打印位于 之后且不在 之前的任何浮点数:
(以忽略时间字段)。
如果您不想将整数值视为浮点数,那么排除时间字段会更简单一些,如下所示:
perl -pe 's/[-+]?[0-9]*\.[0-9]+/sprintf("%.2f",$&)/e' log
浮点正则表达式取自使用正则表达式匹配浮点数
答案3
通过一个小的正则表达式应该可以工作
sed -r 's/([0-9]+\.[0-9]{2})[0-9]*/\1/' your_file
快速解释一下它正在寻找:
- 数字
- 一个点
- 另外 2 位数字
- 任意数量的数字
它会用前三个替换掉所有部分。本质上就是砍掉最后一部分。
该命令只会输出更改。-i
如果您希望它直接编辑文件,请在其中添加一个。如果这实际上不是一个文件,您也可以将内容导入并重定向到sed
:
$ sed -r 's/([0-9]\.[0-9]{2})[0-9]*/\1/' <<EOF
> [General]
> Date=2016-01-20
> Timestamp=2016-01-20T12:30:00
>
> [Dewpoint]
> Low=-17.7041803458378
> LTime=14:55
> High=-13.1057525836829
> HTime=13:42
>
> [Solar]
> SunshineHours=4.78333333333332
> SunshineHoursToMidnight=0.750000000000001
> EOF
[General]
Date=2016-01-20
Timestamp=2016-01-20T12:30:00
[Dewpoint]
Low=-17.70
LTime=14:55
High=-13.10
HTime=13:42
[Solar]
SunshineHours=4.78
SunshineHoursToMidnight=0.75