stirng.gsub 和 正则 实现 千分位格式化数字
问题
接到了个需求:
千分位格式化数字,可能有小数点。
比如:
1234567 -> 1,234,567
1234567.8901 -> 1,234,567.8901
最后效果就是小数点左边的部分,每三个数字加一个逗号。
实现:
- 最直接的肯定就是用字符串截取,先找到小数点,分割成两部分;再把前半部分3个为一组分开,再重新带上逗号拼接。
- 也可以用 正则 + 字符串替换。通过模式匹配,从头开始每三个数字后加一个逗号,不断替换直到最后或小数点位置。
第一种方法通俗易懂简单明了,但是麻烦;第二种代码相对简(xiu)洁(ji)一些。
分析
character class
字符类,用于表示字符的集合。
1 | x: (这里 x 不能是 魔法字符 ^$()%.[]*+-? 中的一员) 表示字符 x 自身。 |
pattern item(模式条目)
模式条目可以是:1
2
3
4
5
6
7
8单个字符类匹配该类别中任意单个字符
单个字符类跟一个 '*', 将匹配零或多个该类的字符。 这个条目总是匹配尽可能长的串;
单个字符类跟一个 '+', 将匹配一或更多个该类的字符。 这个条目总是匹配尽可能长的串;
单个字符类跟一个 '-', 将匹配零或更多个该类的字符。 和 '*' 不同,这个条目总是匹配尽可能短的串;
单个字符类跟一个 '?', 将匹配零或一个该类的字符。 只要有可能,它会匹配一个;
%n, 这里的 n 可以从 1 到 9; 这个条目匹配一个等于 n 号捕获物(后面有描述)的子串。
%bxy, 这里的 x 和 y 是两个明确的字符; 这个条目匹配以 x 开始 y 结束, 且其中 x 和 y 保持 平衡 的字符串。 意思是,如果从左到右读这个字符串,对每次读到一个 x 就 +1 ,读到一个 y 就 -1, 最终结束处的那个 y 是第一个记数到 0 的 y。 举个例子,条目 %b() 可以匹配到括号平衡的表达式。
%f[set], 指 边境模式; 这个条目会匹配到一个位于 set 内某个字符之前的一个空串, 且这个位置的前一个字符不属于 set 。 集合 set 的含义如前面所述。 匹配出的那个空串之开始和结束点的计算就看成该处有个字符 '\0' 一样。
pattern(模式)
指一个模式条目的序列。
在模式最前面加上符号 ‘^’ 表示从字符串的开始处做匹配。
在模式最后加上符号 ‘$’ 表示匹配到字符串的结尾。
如果 ‘^’ 和 ‘$’ 出现在其它位置,它们均没有特殊含义,只表示自身。
capture(捕获)
模式可以在内部用小括号括起来(表示一个子模式),这些子模式称为 捕获物。
当匹配成功时,由捕获物匹配到的字符串中的子串被保存起来用于之后用途。
捕获物由它们左括号的次序来编号。
ext: 空的捕获() 将捕获到当前字符串的位置(一个数字);例如,”()%a%d()” 作用到 “ltree98” 上,将产生两个捕获物: 5和7。
string.gsub
string.gsub (目标串, 匹配串, 替换串 [, 替换次数])
返回一个经过替换串替换后的目标串的副本及替换次数。
如果替换串是string则直接用替换串替换匹配串即可。当里面字符存在’%’时,则代表调用捕获子串,捕获子串序列在1-9,0代表全部,%%代表%字符。
如果替换串是table类型,在每次匹配调用,并用第一个捕获子串来作为table的key值查询。
如果替换串是function类型,在每次匹配调用,并将所有子串按顺序作为函数参数。
任何情况下,如果匹配串没有捕获子串,那么整个匹配串作为捕获子串继续执行。
如果table或者function返回的是
- string类型,直接用
- number类型,直接用
- false,不替换
- nil,不替换
- 其他,报错
方案
1 | function formatnumberthousands(num) |
参考资料