人间日常

所行皆过往,所愿皆成真

正在加载今日诗词....

巧妙使用正则——去除小数点后多余的零

巧妙使用正则——去除小数点后多余的零

直接上代码

const arr=['1200.00100','1200.00000','1200.','1200','1200.10000','0.120010000','0.000011111']
const regexp=/(?:\.0*|(\.\d+?)0+)$/
arr.forEach((item)=>{
    console.log(item.replace(regexp,'$1'))
})

// > 1200.001
// > 1200
// > 1200
// > 1200
// > 1200.1
// > 0.12001
// > 0.000011111

正则可视化:

image

推荐个可视化网址:https://regexper.com/

再解释下正则的意思(?:.0*|(.\d+?)0+)$

先分解成4部分

  1. (?:reg1|reg2) - 它是一个正则分组非捕获组,要么匹配reg1,要么匹配reg2,优先匹配reg1,加上?:不对捕获组记录
  2. .0* - 表示匹配一个.开头,后边跟着0或0个以上数量的0,且不进行捕获,所以在填充$1时,就是个空值
  3. (.\d+?)0+ - 它是一个捕获组,匹配一个.开头后边跟着非贪婪(懒惰)匹配任意数字,接着在末尾尽可能多的匹配0这个字符,匹配完成后,生成一个捕获组内容
  4. $ - 表示匹配结果需要以0作为结尾

正则分组

  • 普通捕获组

    从正则表达式左侧开始,每出现一个左括号”(“记做一个分组,分组编号从 1 开始。0 代表整个表达式。

    对于时间字符串:2017-04-25,表达式如下

    (\\d{4})-((\\d{2})-(\\d{2}))
    

    有 4 个左括号,所以有 4 个分组:

    | 编号 | 捕获组 | 匹配 |
    | :—- | :———————————— | :————- |
    | 0 | (\d{4})-((\d{2})-(\d{2})) | 2017-04-25 |
    | 1 | (\d{4}) | 2017 |
    | 2 | ((\d{2})-(\d{2})) | 04-25 |
    | 3 | (\d{2}) | 04 |
    | 4 | (\d{2}) | 25 |

  • 命名捕获组

    每个以左括号开始的捕获组,都紧跟着 ?,而后才是正则表达式。

    对于时间字符串:2017-04-25,表达式如下:

    (?\\d{4})-(?(?\\d{2})-(?\\d{2}))
    

    有 4 个命名的捕获组,分别是:

    | 编号 | 名称 | 捕获组 | 匹配 |
    | :—- | :—— | :—————————————— | :————- |
    | 0 | 0 | (?\d{4})-(?(?\d{2})-(?\d{2})) | 2017-04-25 |
    | 1 | year | (?\d{4})- | 2017 |
    | 2 | md | (?(?\d{2})-(?\d{2})) | 04-25 |
    | 3 | month | (?\d{2}) | 04 |
    | 4 | date | (?\d{2}) | 25 |

    命名的捕获组同样也可以使用编号获取相应值。

非捕获组

在左括号后紧跟 ?:,而后再加上正则表达式,构成非捕获组 (?:Expression)

对于时间字符串:2017-04-25,表达式如下:

(?:\\d{4})-((\\d{2})-(\\d{2}))

这个正则表达式虽然有四个左括号,理论上有 4 个捕获组。但是第一组 (?:\d{4}),其实是被忽略的。当使用 matcher.group(4) 时,系统会报错。

编号 捕获组 匹配
0 (\d{4})-((\d{2})-(\d{2})) 2017-04-25
1 ((\d{2})-(\d{2})) 04-25
2 (\d{2}) 04
3 (\d{2}) 25

非贪婪(懒惰)匹配

贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。如上面使用模式p匹配字符串str,结果就是匹配到:abcaxc(ab*c)。

非贪婪匹配:就是匹配到结果就好,就少的匹配字符。如上面使用模式p匹配字符串str,结果就是匹配到:abc(ab*c)。

问号可以表示重复前面内容的0次或一次,也就是要么不出现,要么出现一次

示例1:

string pattern1 = @"a.*?c";   // non-greedy match 
Regex regex = new Regex(pattern1);
regex.Match("abcabc"); // return "abc"

## 结果:abc

示例2:

import re
s='hello 1234567 world'
res = re.match('he.*?(\d).*rld$',s)
print(res.group(1))

## 结果:123456

常用非贪婪表达式

*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

关注我

湘ICP备2020021380号-1
© 2014 - 2024 SIWEN.PENG