就地格式化文件特定列中的数字

就地格式化文件特定列中的数字

我正在尝试将Amountcol 格式化为 2 位十进制格式,1000例如1000.00

我有一个如下所示的示例文件

Bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100||
xyz|we||100.1||
xyz|we|paid for inv# 34VM23-SEP-20|23459900.00||
xyz|errt||-230.0||
xyz|ss||234.78||
xyz|we|valid|990.2||
xyz|we|9922.9 paid|9922.9||
xyz|we||.9||
xyz|we||.0||
xyz|we||.00||

我尝试了awk -F"|" '{OFS=FS}''{printf ("%.2f",$4) ; print }' test.csv导致

0.00Bank|Branch|Comment|Amount|Extra1|Extra2
100.00xyz|we||100||
100.10xyz|we||100.1||
23459900.00xyz|we|paid for inv# 34VM23-SEP-20|23459900.00||
-230.00xyz|errt||-230.0||
234.78xyz|ss||234.78||
990.20xyz|we|valid|990.2||
9922.90xyz|we|9922.9 paid|9922.9||
0.90xyz|we||.9||
0.00xyz|we||.0||
0.00xyz|we||.00||
0.00

另外我想避免标题行并替换到原始文件中。请为我指出正确的方向。谢谢

答案1

你的 awk 代码有缺陷,你首先打印 $4 的修改值加上整行

正确的版本是这样的:awk -F"|" 'NR<=1{print $0;next} {{printf($1"|" $2"|"$3"|%.2f|"$5"|"$6"\n",$4)}}' test

$ awk -F"|" 'NR<=1{print $0;next}  {{printf($1"|" $2"|"$3"|%.2f|"$5"|"$6"\n",$4)}}' test
bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100,00||
xyz|we||100,00||
xyz|we|paid for inv# 34VM23-SEP-20|23459900,00||
xyz|errt||-230,00||
xyz|ss||234,00||
xyz|we|valid|990,00||
xyz|we|9922.9 paid|9922,00||
xyz|we||0,00||
xyz|we||0,00||
xyz|we||0,00||

您需要打印所有未更改的字段以及根据您的意愿修改的字段 4。要不处理第一行,请测试 NR 并仅打印该行而不进行修改,然后继续处理next第二行

编辑我的 awk 版本可能有问题,因为原始命令和我的版本不保留存在的十进制数字并将其设置为 0。我想这是否适合您。我猜这与我的当地人有关。例如在我的机器上234.78变成了。234,00

另一个解决方案来自保罗学究的注释是直接更改 $4 的值并在之后打印:

plonky@sd-143012:~/work$ awk -F '|' '{ {OFS=FS} if (FNR > 1) $4 = sprintf ("%.2f", $4); print; }'  test
bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100,00||
xyz|we||100,00||
xyz|we|paid for inv# 34VM23-SEP-20|23459900,00||
xyz|errt||-230,00||
xyz|ss||234,00||
xyz|we|valid|990,00||
xyz|we|9922.9 paid|9922,00||
xyz|we||0,00||
xyz|we||0,00||
xyz|we||0,00||

答案2

像这样的东西应该有效:

awk -F '|' 'FNR>1 {printf "%s|%s|%s|%.2f|%s|%s\n", $1,$2,$3,$4,$5,$6}'

-F '|'已经有了,但是是字段分隔符。

您说您想跳过第一行,这可以通过FNR>1.FNR是当前输入文件中的输入记录号。由于 awk 是基于行的读取器,所以>1第一行之后的处理

使用printf也是正确的,但是您的语法无法达到您想要的结果。您可以根据要求展开以打印整行。

您还忘记了\n行尾的行返回,这就是您得到奇怪布局的原因。

答案3

磨坊主

mlr --csvlite --fs '|' put '$Amount = fmtnum($Amount,"%.2f")' file

要就地修改文件,请添加-I命令行开关。

答案4

使用 Raku(née Perl6)

我可能会使用 Raku 做一些非常机械的事情,通过显式splitjoin调用。这样您就可以使用相同的数字格式代码更改为另一个列分隔符(例如逗号):

~$ raku -e 'for lines.skip(1) {my @a = .split("|"); .subst(@a[3], sprintf( "%.2f", @a[3] )).join("|").put };'

另外,我编写了代码来创建一个tmp文件,该文件首先保存标题,然后附加格式化的数据行。不是你所要求的——但它有效。此外,使用此代码无需知道每行的总列数(超出您尝试格式化的列)。

把它们放在一起:

~$ raku -e '.say for lines[0];' < bank.txt > tmp
~$ raku -e 'for lines.skip(1) {my @a = .split("|"); .subst(@a[3], sprintf( "%.2f", @a[3] )).join("|").put };' < bank.txt >> tmp

输出:

Bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100.00||
xyz|we||100.10||
xyz|we|paid for inv# 34VM23-SEP-20|23459900.00||
xyz|errt||-230.00||
xyz|ss||234.78||
xyz|we|valid|990.20||
xyz|we|9922.90 paid|9922.9||
xyz|we||0.90||
xyz|we||0.00||
xyz|we||0.00||

HTH。

https://raku.org/

相关内容