Answers:
与sed
:
$ echo "123456789" | sed 's/\([[:digit:]]\{3\}\)\([[:digit:]]\{3\}\)\([[:digit:]]\{3\}\)/\1,\2,\3/g'
123,456,789
(请注意,这仅适用于9位数字!)
或与此sed
:
$ echo "123456789" | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta'
123,456,789
与printf
:
$ LC_NUMERIC=en_US printf "%'.f\n" 123456789
123,456,789
echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g"){sub(",$",""); print}'
sed
仅当数字正好是9位数字时才有效。该printf
不上的zsh工作。因此,第二个sed
答案可能是最好的。
echo 123456789 | awk '{printf ("%'\''d\n", $0)}'
(显然,它并不总是在Linux上可用!?但是在AIX和Solaris上可以正常使用)
bash
的printf
支持几乎所有你可以在做printf
C函数
type printf # => printf is a shell builtin
printf "%'d" 123456 # => 123,456
printf
来自coreutils会做同样的事情
/usr/bin/printf "%'d" 1234567 # => 1,234,567
zsh
,此处更新了帖子。
vsnprintf
。在GNU / Linux系统上,glibc似乎至少从1995
locale -a
。我不得不使用en_US.utf8
您可以使用numfmt:
$ numfmt --grouping 123456789
123,456,789
要么:
$ numfmt --g 123456789
123,456,789
请注意,numfmt不是POSIX实用程序,它是GNU coreutils的一部分。
-d, --grouping
因为双连字符需要较长的选项?
--g
工作正常,我来代替--grouping
,即numfmt --g 1234567890
和numfmt --grouping 1234567890
做同样的事情。它是一个非常有用的小工具。
cat <<'EOF' |
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
EOF
perl -wpe '1 while s/(\d+)(\d\d\d)/$1,$2/;'
产生:
13,407,807,929,942,597,099,574,024,998,205,846,127,479,365,820,592,393,377,723,561,443,721,764,030,073,546,976,801,874,298,166,903,427,690,031,858,186,486,050,853,753,882,811,946,569,946,433,649,006,084,096
这可以通过将数字字符串分成2组来完成,右侧的组为3位,左侧的组为剩余的位数,但至少为一位。然后,将所有内容替换为两组,并用逗号分隔。这一直持续到替换失败为止。选项“ wpe”用于错误列表,将语句括在带有自动打印的循环中,并将下一个参数作为perl“程序”(有关详细信息,请参见命令perldoc perlrun)。
最好的祝福...干杯
BASH
/ AWK
替代方案,因此他可能PERL
以前没有使用过。无论如何,最好解释一下该命令的作用-特别是对于单线作业。
对我而言,一个常见的用例是修改命令管道的输出,以便用千位分隔符打印十进制数字。我宁愿使用一种可以针对Unix管道中的任何输出动态自定义的技术,而不是编写函数或脚本。
我发现printf
(由Awk提供)是实现这一目标的最灵活,最难忘的方法。POSIX将单引号/单引号字符指定为用于格式化十进制数字的修饰符,它的优点是可以识别语言环境,因此不限于使用逗号字符。
当从Unix Shell运行Awk命令时,在用单引号分隔的字符串内输入单引号字符可能会很困难(以避免位置变量的Shell扩展,例如$1
)。在这种情况下,我发现输入单引号字符的最可读,最可靠的方法是将其作为八进制转义序列(以开头\0
)输入。
例:
printf "first 1000\nsecond 10000000\n" |
awk '{printf "%9s: %11\047d\n", $1, $2}'
first: 1,000
second: 10,000,000
管道的模拟输出,显示哪些目录使用的磁盘空间最多:
printf "7654321 /home/export\n110384 /home/incoming\n" |
awk '{printf "%22s: %9\047d\n", $2, $1}'
/home/export: 7,654,321
/home/incoming: 110,384
如何在awk中转义单引号中列出了其他解决方案。
注意:正如在“ 打印单引号”中所警告的那样,建议避免使用十六进制转义序列,因为它们无法在不同系统上可靠地工作。
\047
。
awk
并bash
具有基于的良好内置解决方案printf
,如其他答案所述。但首先,sed
。
对于sed
,我们需要“手动”执行。一般规则是,如果您有四个连续的数字,然后是一个非数字(或行尾),则应在第一和第二个数字之间插入一个逗号。
例如,
echo 12345678 | sed -re 's/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/'
将打印
12345,678
我们显然需要继续重复该过程,以便继续添加足够的逗号。
sed -re ' :restart ; s/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/ ; t restart '
在中sed
,t
命令指定一个标签,如果上一个s///
命令成功执行,则该标签将跳转到该标签。因此:restart
,我使用定义了一个标签,以便其跳回。
这是一个bash演示(在ideone上),可以使用任意数量的数字:
function thousands {
sed -re ' :restart ; s/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/ ; t restart '
}
echo 12 | thousands
echo 1234 | thousands
echo 123456 | thousands
echo 1234567 | thousands
echo 123456789 | thousands
echo 1234567890 | thousands
$ echo 1232323 | awk '{printf(fmt,$1)}' fmt="%'6.3f\n"
12,32,323.000
如果您正在查看BIG编号,则无法使上述解决方案起作用。例如,让我们得到一个很大的数字:
$ echo 2^512 |bc -l|tr -d -c [0-9]
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
注意我需要tr
从bc中删除反斜杠换行符输出。这个数字太大了,无法在awk中视为浮点数或固定位数字,我什至不想构建一个足以容纳sed中所有数字的正则表达式。相反,我可以将其反转并将逗号放在三位数的组之间,然后将其取消反转:
echo 2^512 |bc -l|tr -d -c [0-9] |rev |sed -e 's/\([0-9][0-9][0-9]\)/\1,/g' |rev
13,407,807,929,942,597,099,574,024,998,205,846,127,479,365,820,592,393,377,723,561,443,721,764,030,073,546,976,801,874,298,166,903,427,690,031,858,186,486,050,853,753,882,811,946,569,946,433,649,006,084,096
awk: run time error: improper conversion(number 1) in printf("%'d
。
a="13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096"
echo "$a" | rev | sed "s#[[:digit:]]\{3\}#&,#g" | rev
13,407,807,929,942,597,099,574,024,998,205,846,127,479,365,820,592,393,377,723,561,443,721,764,030,073,546,976,801,874,298,166,903,427,690,031,858,186,486,050,853,753,882,811,946,569,946,433,649,006,084,096
sed 's/^,//g'
。
我也想有部分后的小数点分隔符正确分离/隔开的,所以我写这个的sed脚本,它使用一些shell变量,以适应区域和个人喜好。它还针对组合在一起的位数考虑了不同的约定:
#DECIMALSEP='.' # usa
DECIMALSEP=',' # europe
#THOUSSEP=',' # usa
#THOUSSEP='.' # europe
#THOUSSEP='_' # underscore
#THOUSSEP=' ' # space
THOUSSEP=' ' # thinspace
# group before decimal separator
#GROUPBEFDS=4 # china
GROUPBEFDS=3 # europe and usa
# group after decimal separator
#GROUPAFTDS=5 # used by many publications
GROUPAFTDS=3
function digitgrouping {
sed -e '
s%\([0-9'"$DECIMALSEP"']\+\)'"$THOUSSEP"'%\1__HIDETHOUSSEP__%g
:restartA ; s%\([0-9]\)\([0-9]\{'"$GROUPBEFDS"'\}\)\(['"$DECIMALSEP$THOUSSEP"']\)%\1'"$THOUSSEP"'\2\3% ; t restartA
:restartB ; s%\('"$DECIMALSEP"'\([0-9]\{'"$GROUPAFTDS"'\}\'"$THOUSSEP"'\)*\)\([0-9]\{'"$GROUPAFTDS"'\}\)\([0-9]\)%\1\3'"$THOUSSEP"'\4% ; t restartB
:restartC ; s%\([^'"$DECIMALSEP"'][0-9]\+\)\([0-9]\{'"$GROUPBEFDS"'\}\)\($\|[^0-9]\)%\1'"$THOUSSEP"'\2\3% ; t restartC
s%__HIDETHOUSSEP__%\'"$THOUSSEP"'%g'
}
一个bash
/ awk
(根据要求)解决方案,无论数字的长度,
如何,都可以使用thousands_sep
,并且与语言环境的设置以及输入中的数字位于何处都可以使用,并且避免在以下位置添加千位分隔符1.12345
:
echo not number 123456789012345678901234567890 1234.56789 |
awk '{while (match($0, /(^|[^.0123456789])[0123456789]{4,}/))
$0 = substr($0, 1, RSTART+RLENGTH-4) "," substr($0, RSTART+RLENGTH-3)
print}'
给出:
not number 123,456,789,012,345,678,901,234,567,890 1,234.56789
随着awk
类似的实现mawk
不支持间隔regex操作符,改变正则表达式来/(^|[^.0123456789])[0123456789][0123456789][0123456789][0123456789]+/
echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g")'