如何向特定列中的数字添加十进制分隔符-Bash

如何向特定列中的数字添加十进制分隔符-Bash,bash,awk,vim,Bash,Awk,Vim,我有一个.txt文件,需要添加逗号作为十进制分隔符,以提高可读性。这些数字只存在于某些列中,我找不到一种方法来实现这一点。列之间用分号分隔,可以包含任何字符。 数字在第三列和第四列 这个 应该变成这样: BitstreamCyberCJK;Freeware;30,275;28,686;v2.0 beta (1998-03-17);Cyberbit.ttf (12.4 MB);Bitstream CyberCJK;Medium (Normal), Book, Roman;TTF;Cove Y.O

我有一个.txt文件,需要添加逗号作为十进制分隔符,以提高可读性。这些数字只存在于某些列中,我找不到一种方法来实现这一点。列之间用分号分隔,可以包含任何字符。 数字在第三列和第四列

这个

应该变成这样:

BitstreamCyberCJK;Freeware;30,275;28,686;v2.0 beta (1998-03-17);Cyberbit.ttf (12.4 MB);Bitstream CyberCJK;Medium (Normal), Book, Roman;TTF;Cove

Y.OzFontN;Freeware;21,957;57,621;v13.00 sfnt rev 5 Pen-Ji (2010-08-24);YOzRN.TTC (13.5 MB);YOzFontN;Regular;TTC;Any
我曾考虑在awk中使用if语句来检查这些列的长度是否大于3,但后来我找不到将逗号放在每三位之间的方法

我尽了最大努力想出了这个办法,但有趣的是,我使用的系统没有运行gawk,我也不知道gawk和awk之间的区别来纠正我的代码

gawk '  BEGIN {OFS=FS=";"} {for(i=1;i<NF;i++) {if($i ~ /^[0-9]+$/) $i = sprintf("%'\''d", $i)}} 1'

gawk'BEGIN{OFS=FS=“;”}{for(i=1;i这将转换所有数字

$ awk -F';' 'function pp(x) {tt=int(x/1000); 
                             return tt?(pp(tt)","(x%1000)):x}
              BEGIN {OFS=FS} 
                    {for(i=1;i<=NF;i++) if($i+0==$i) $i=pp($i)}1' file


BitstreamCyberCJK
BitstreamCyberCJK;Freeware;30,275;28,686;v2.0 beta (1998-03-17);Cyberbit.ttf (12.4 MB);Bitstream CyberCJK;Medium (Normal), Book, Roman;TTF;Cove


Y.OzFontN
Y.OzFontN;Freeware;21,957;57,621;v13.00 sfnt rev 5 Pen-Ji (2010-08-24);YOzRN.TTC (13.5 MB);YOzFontN;Regular;TTC;Any
$awk-F';''函数pp(x){tt=int(x/1000);
返回tt?(pp(tt)”,(x%1000)):x}
开始{OFS=FS}
{对于(i=1;i这应该可以:

LC_ALL=en_US.UTF-8 awk -F';'  'BEGIN{ OFS=";" }{ $4=sprintf("%'"'"'d", $4); $3=sprintf("%'"'"'d", $3) ; print $0}' file.txt
希望它有用

sed -r ':a; s/;([0-9]+)([0-9]{3})(([,][0-9]*)*)($|[;])/;\1,\2\3\5/g; ta' textfile
说明:
sed-r
:避免反斜杠
:a;
:重复替换的标签
;([0-9]+)
:在接下来的三个数字之前至少有一个数字
([0-9]{3})
:三位数字
(([,][0-9]{3})*)
:可选的三位逗号集
($|[;])
:行尾或字段尾
/;\1\2\3\5/g;
:用带附加逗号的双数据替换

ta
:当更换成功时,返回标签a并重复假设您是因为
sprintf而询问(“%”…
无法在UNIX设备上使用awk,一种方法是在每个数字上加0,使其成为3位数的倍数,然后在每3位数前加一个逗号,然后删除前导的0和逗号:

$ awk 'BEGIN{OFS=FS=";"} {for (i=3; i<=4; i++) {$i=sprintf("%099d",$i); gsub(/.../,",&",$i); sub(/^(,0+)+/,"",$i)} } 1' file
BitstreamCyberCJK;Freeware;30,275;28,686;v2.0 beta (1998-03-17);Cyberbit.ttf (12.4 MB);Bitstream CyberCJK;Medium (Normal), Book, Roman;TTF;Cove
Y.OzFontN;Freeware;21,957;57,621;v13.00 sfnt rev 5 Pen-Ji (2010-08-24);YOzRN.TTC (13.5 MB);YOzFontN;Regular;TTC;Any

格式中没有循环,因此即使对于大的数字也应该是有效的。

目标是在问题中添加一些自己的代码,以显示至少您自己为解决这个问题所做的研究工作。我写了这篇文章,但问题是我不熟悉gawk和awk的区别以及我正在尝试的系统上载时不运行gawk.gawk'BEGIN{OFS=FS=“;”}{for(i=1;我想你总是想要三位小数吗?是的,我想我应该用逗号来改变这些列中的最后三位。但是找不到一种方法。这是否适用于
$”
-样式的字符串,所以格式说明符中的单引号可能只是
\
?我永远记不起这是否是特定于某个特定的shell或POSIX对象。
“”“
在功能上与
”\'
相同-它们都从awk脚本中转义,让shell提供一个
'
,然后在awk解释它之前成为awk脚本的一部分。您可以使用
\047
的八进制转义序列对
获得相同的功能。
$ awk 'BEGIN{OFS=FS=";"} {for (i=3; i<=4; i++) {$i=sprintf("%099d",$i); gsub(/.../,",&",$i); sub(/^(,0+)+/,"",$i)} } 1' file
BitstreamCyberCJK;Freeware;30,275;28,686;v2.0 beta (1998-03-17);Cyberbit.ttf (12.4 MB);Bitstream CyberCJK;Medium (Normal), Book, Roman;TTF;Cove
Y.OzFontN;Freeware;21,957;57,621;v13.00 sfnt rev 5 Pen-Ji (2010-08-24);YOzRN.TTC (13.5 MB);YOzFontN;Regular;TTC;Any
$ awk 'BEGIN{OFS=FS=";"} {for (i=3; i<=4; i++) {$i=sprintf("%0*d",int((length($i)+2)/3)*3,$i); gsub(/.../,",&",$i); sub(/^(,0+)+/,"",$i)} } 1' file
BitstreamCyberCJK;Freeware;30,275;28,686;v2.0 beta (1998-03-17);Cyberbit.ttf (12.4 MB);Bitstream CyberCJK;Medium (Normal), Book, Roman;TTF;Cove
Y.OzFontN;Freeware;21,957;57,621;v13.00 sfnt rev 5 Pen-Ji (2010-08-24);YOzRN.TTC (13.5 MB);YOzFontN;Regular;TTC;Any