kangkai124 / blog

开发笔记
https://kangkai124.github.io/blog/
MIT License
26 stars 4 forks source link

略懂正则 #28

Open kangkai124 opened 5 years ago

kangkai124 commented 5 years ago

一些例子

例子来自 老姚 正则迷你书v1.1

正则可视化来自 regulex

kangkai124 commented 5 years ago

16进制颜色值

/#([a-fA-F0-9]{3}|[a-fA-F0-9]{6})/g

image

kangkai124 commented 5 years ago

24小时时间

/([01][0-9]|2[0-3]):[0-5][0-9]$/g

image

kangkai124 commented 5 years ago

日期YYYY-MM-DD

/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/g

image

kangkai124 commented 5 years ago

window 操作系统文件路径

盘符:\文件夹\文件夹\文件夹\
/^[a-zA-Z]:\\([^\\:*<>|\r\n/]+\\)*([^\\:*<>|\r\n/]+)?$/

image

kangkai124 commented 5 years ago

字符组

字符组 具体含义
\d 表示 [0-9]。表示是一位数字。 记忆方式:其英文是 digit(数字)。
\D 表示 [^0-9] 。表示除数字外的任意字符。
\w 表示 [0-9a-zA-Z_]。表示数字、大小写字母和下划线。 记忆方式:w 是 word 的简写,也称单词字符。
\W 表示 [^0-9a-zA-Z_]。非单词字符。
\s 表示 [ \t\v\n\r\f]。表示空白符,包括空格、水平制表符、垂直制表符、换行符、回车符、换页 符。 记忆方式:s 是 space 的首字母,空白符的单词是 white space。
\S 表示 [^ \t\v\n\r\f]。 非空白符。
. 表示 [^\n\r\u2028\u2029]。通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符 除外。 记忆方式:想想省略号 ... 中的每个点,都可以理解成占位符,表示任何类似的东西。

量词

量词 具体含义
{m,} 表示至少出现 m 次。
{m} 等价于 {m,m},表示出现 m 次。
? 等价于 {0,1},表示出现或者不出现。 记忆方式:问号的意思表示,有吗?
+ 等价于 {1,},表示出现至少一次。 记忆方式:加号是追加的意思,得先有一个,然后才考虑追加。
* 等价于 {0,},表示出现任意次,有可能不出现。 记忆方式:看看天上的星星,可能一颗没有,可能零散有几颗,可能数也数不过来。
kangkai124 commented 5 years ago

惰性量词和贪婪量词

惰性量词 贪婪量词
{m,n}? {m,n}
{m,}? {m,}
?? ?
+? +
*? *
kangkai124 commented 5 years ago
位置匹配 具体含义
^ 匹配开头,多行匹配中匹配行开头
$ 匹配结尾,多行匹配中匹配行结尾
m 多行匹配模式
\b 单词边界,具体就是 \w 与 \W 之间的位置,也包括 \w 与 ^ 之间的位置,和 \w 与 $ 之间的位置
\B 非单词边界,具体说来就是 \w 与 \w、 \W 与 \W、^ 与 \W,\W 与 $ 之间的位置
(?=p) (?=p),其中 p 是一个子模式,即 p 前面的位置,或者说,该位置后面的字符要匹配 p
(?!p) (?!p) 就是 (?=p) 的反面意思
kangkai124 commented 5 years ago

数字的千位分隔符表示法

const toThousands = num => `${num}`.replace(/(?!^)(?=(\d{3})+$)/g, ',')
console.log(toThousands(123456789))  // 123,456,789

image

const toThousands2 = num => `${num}`.replace(/(\d)(?=(\d{3})+$)/g, "$1,")
console.log(toThousands2(123456789))  // 123,456,789

image

kangkai124 commented 5 years ago

货币格式化

1888  ==>  $ 1,888.00
const format = num => 
    num.toFixed(2).replace(/\B(?=(\d{3})+\b)/g, ',').replace(/^/, '$ ')

console.log(format(1888))  //  $ 1,888.00
kangkai124 commented 5 years ago

验证密码

密码长度 6-12 位,由数字、小写字符和大写字母组成,但必须至少包括 2 种字符。

  1. 不考虑“但必须至少包括 2 种字符”这一条件
    var regex = /^[0-9A-Za-z]{6,12}$/
  2. 假设,要求的必须包含数字
    var regex = /(?=.*[0-9])^[0-9A-Za-z]{6,12}$/
  3. 同时包含数字和小写字母
    var regex = /(?=.*[0-9])(?=.*[a-z])^[0-9A-Za-z]{6,12}$/
  4. 最终答案:
    /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[0-9A-Za-z]{6,12}$/

image

解释一下 ?=.*[0-9]. 匹配任意字符(换行符等除外),* 表示0个或多个,在加上一个数字,意思就是0个或多个字符(字符也可能是数字)加一个数字,所以就是至少有一个数字,即包含数字。

还有,^ 之前的是匹配位置,等位置匹配完成后,再匹配字符。

kangkai124 commented 5 years ago

上题的另外一种解法

“至少包含两种字符” 的意思就是说,不能全部都是数字,也不能全部都是小写字母,也不能全部都是大写 字母。

那么要求“不能全部都是数字”,对应的正则是:

/(?!^[0-9]{6,12}$)^[0-9A-Za-z]{6,12}$/

最终答案是:

/(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/
kangkai124 commented 5 years ago

匹配多种日期格式

2016-06-06
2016/06/06
2016.06.06
/\d{4}(-|\/|\.)\d{2}\1\d{2}/

image

kangkai124 commented 5 years ago

每个单词首字母大写


const titleize = str => str.toLowerCase().replace(/(?:^|\s)\w/g, c => c.toUpperCase())
console.log(titleize("my name is kk"))
// My Name Is Kk

image

kangkai124 commented 5 years ago

驼峰转中划线

const dasherize = str =>
    str.replace(/(?!^)([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase()

dasherize("MozTransform") // moz-transform
kangkai124 commented 5 years ago

匹配成对标签

const regex = /<([^>]+)>[\d\D]*<\/\1>/
regex.test("<div>regular expression</div>")

image

kangkai124 commented 5 years ago

操作符权重

优先级从上至下,由高到低

操作符描述 操作符 优先级
转义符 \ 1
括号和方括号 (...)、(?:...)、(?=...)、(?!...)、[...] 2
量词限定符 {m}、{m,n}、{m,}、?、*、+ 3
位置和序列 ^、$、\元字符、一般字符 4
管道符(竖杠) | 5