千位分隔符的完整攻略
千位分隔符[1]是很常见的需求,但是输入文本千变万化,如何才能准确添加千分符呢? 纯整数情况
纯整数大概是所有情况里最简单的一种,我们只要正确匹配出千分位就好了。 观察上面的数字,我们可以得出千分位的特征是到字符串终止位有 3n 个数字,不包括起始位。于是可以得到这样的函数: javascriptlet milliFormat = (num) => { return num && num.toString().replace(/(?=(?!^)(d{3})+$)/g,',') } 但是往往现实没有那么乐观: 小数的情况
遇到小数时,我们的希望只针对整数部分添加千分符,这时问题就变得稍稍有些棘手了。 如果正则引擎支持逆序环视[2],我们可以这样构造正则表达式: javascript(?<=^d+)(?=(d{3})+b) 但是多数语言并不支持逆序环视,所以我们要变通一下: 1. 拿到小数的整数部分也就是起始位到小数点(非数字)之间的部分,可以这样实现: javascript^d+ 2. 为整数部分添加千分符这一步可以利用我们之前的实现,整合在一起如下: javascriptlet milliFormat = (num) => { return num && num.toString() .replace(/^d+/g,(m) => m.replace(/(?=(?!^)(d{3})+$)/g,')) } 这个函数对整、小数都能正确处理:
但在实际中,我们还可能传入一个整、小数混合的字符串: 整、小数混合字符串
这时我们就不能继续用字符串起终点
哦不!连小数部分也被添上千分符了!怎样才能避开小数部分? 重新审视我们捕获整数部分所用到的正则: javascriptbd+
javascript(^|s)d+
咦,多出来一个空白符?别着急,看看我们用来匹配千分位的正则: javascript(?=(?!^)(d{3})+$) 判断条件是非起点、到结尾有 3n 个数字的位置,现在为了去掉这多出来的一个空格,我们应将起始条件改成单词边界: javascript(?=(?!b)(d{3})+$) 完整函数如下: javascriptlet milliFormat = (input) => { return input && input.toString() .replace(/(^|s)d+/g,(m) => m.replace(/(?=(?!b)(d{3})+$)/g,')) }
酷炫!我们已经能自如应付各种数值的混合了!这是耳边幽幽飘来产品经理的声音:如果我传入含有非数字的字符串呢…… 复杂字符串
在上一个例子中,我们只判断了起始边界,于是
依据这个我们可以这样做: javascript(^|s)d+(?=.?d*($|s)) 这个正则表示匹配目标应以字符串起始位或空白符开始,紧接着是数字,数字的右边只允许继续是数字或者一个小数点、直到字符串结尾或下一个空格处。来看看它的匹配效果:
好样的!我们已经能精确匹配出正确的部分了!继续用之前的千分位模式封装: javascriptlet milliFormat = (() => { const DIGIT_PATTERN = /(^|s)d+(?=.?d*($|s))/g const MILLI_PATTERN = /(?=(?!b)(d{3})+$)/g return (input) => input && input.toString() .replace(DIGIT_PATTERN,(m) => m.replace(MILLI_PATTERN,')) })()
酷炫!全部都正确处理了!回家睡觉!
更复杂的世界谢 @vc1 指出,在现实中可能还会有更加复杂的情况,如: '1234 1234.56 $1234 $-1234 $-1234.56e+7 123...e3' 容我先去买根上吊绳…… (全文完) 参考资料
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |