我正在尝试将Amount
col 格式化为 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
答案4
使用 Raku(née Perl6)
我可能会使用 Raku 做一些非常机械的事情,通过显式split
和join
调用。这样您就可以使用相同的数字格式代码更改为另一个列分隔符(例如逗号):
~$ 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。