#!/usr/bin/perl
use strict;
use warnings;
my $num = 1234556789;
#纯数据模式
$num =~ s/(?<=\d)(?=(\d{3})+$)/,/g; #零宽断言,(?=exp)匹配exp前面的位置
print $num,"\n";
#带有小数点模式
$num = 123456.1234;
$num =~ s/(?<!\.\d)(?<=\d)(?=(\d{3})+\b)/,/g;
print $num,"\n";
#小数位大于4位之后,使用下面的方法
#\K 模式,可变长否定向后环视;\K容许在它之前的模式只匹配而不被替换。替换操作只对\K之后的字符串部分有效。
#连续匹配:\G,\G 定位标记指定匹配必须出现在上一个匹配结束的地方。
$num = 1234567.12345;
$num =~ s/(?<!\.)(?:\b|\G)\d+?\K(?=(\d{3})+\b)/,/g;
print $num,"\n";
# (?<!\.) 该位置之前补包含.
# (?:\b|\G)单词开头后或上一次匹配结束的地方
# \d+? 至少有一个数字,后面问号是非贪婪符号
OUTPUT:
1,234,556,789
123,456.1234
1,234,567.12345
匹配过程(含5位小数):
1. 首先通过(?<!\.)(?:\b|\G)\d+?,匹配到123456;
2. 由于\d+?是非贪婪的,所以匹配到1_234567,即匹配到1和2之间的位置;
3. 第二次匹配,由于有\b|\G,所以上次匹配到的地方开始,即从2开始,匹配到1,234_567;
(?=exp) 零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp;
(?<exp) 零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配exp;
(?!exp) 零宽度负预测先行断言,它断言自身出现的位置的后面不能匹配表达式exp;
(?<!exp) 零宽度负回顾后发断言,它断言自身出现的位置的前面不能匹配表达式exp;