别再说概念了!直接告诉我这些常用正则表达式是怎么写出来的行不行?

发表于 2年以前  | 总阅读数:409 次

作为一名程序员,不会写正则表达式总感觉少了点什么,不要求你能把正则玩出花来,但最起码要对常用的正则表达式手到擒来,刚毕业的我对于正则也是一头雾水,不过学会它也就一篇教程的事情[1]

本文我不会再浪费带宽把正则的规则再次重复一遍,而是从实际入手,直接告诉你为什么这么写

16进制颜色

按照规则来

  1. # 开头
  2. 后面紧跟着6个字符或者3个字符作为结尾,这些字符可以是 a-f 的小写字母、A-F的大写字母、数字

第一句,可以写成 /^#/;第二句,[a-fA-F0-9] 表示任意的 a-fA-F0-963的个数可以用 {6}{3}进行表示,那么3个字符就是 [a-fA-F0-9]{3},6个字符就是 [a-fA-F0-9]{6},这两个都有可能,用一个或(|)符号来连接:([a-fA-F0-9]{6}|[a-fA-F0-9]{3}),最后结尾可以用个 $

所有合到一起就是 /^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/

链接

目标是匹配出协议、域名、端口号portpathsearch

1 . 协议

合法的协议有 httphttps,还有一个是自适应协议,即不明确加协议,跟当前页面的协议保持一致,所以以下都是合法的:http://toutiao.comhttps://toutiao.com//toutiao.com。这三个协议组成的链接共同点是肯定有 // 字符串,在 //的前面可能是 https: 也可能是 http: 也可以没有任何字符串 先按照 https:// 这种写规则:^https:\/\/,其中的 s 字符可能有也可能没有,所以使用 ? 修饰:^https?:\/\/,又因为 https?:可能没有,所以这个字符串也用 ?修饰:^(https?:)?\/\/

2 . 域名

域名的前面可能是 //,从 //往后面匹配,只要没有代表 :port、代表 search?、代表 path/,那么就都属于域名:[^?:/]+

3 . 端口号 port

端口号肯定以 : 开头,后面跟着的只要是数字就都属于 port:\d+,由于不一定有端口号,所以用 ? 修饰:(:\d+)?

4 . path

肯定以 / 开头,只要不遇到代表 search?,那么就都属于 path\/[^?]*,由于可能没有 path,所以用 ? 修饰:(\/[^?]*)? 5. search 肯定以 ? 开头,后面所有的字符都属于 search(不考虑 hash 路由):\?(.*),由于可能没有 search,所以用 ? 修饰:(\?.*)?

最后把上面所有规则合起来就是提取链接的完整正则了,考虑到需要精确提取所需要的部分,所以会对所需要提取的部分加上小括号,结果为:/^((https?):)?\/\/([^?:/]+)(:(\d+))?(\/[^?]*)?(\?(.*))?/

邮箱

以前在知乎上看到过一段邮箱正则,号称是最符合标准的正则表达式,那条正则的体积好像有几十KB吧,总之很长,现在找不到了,这里只关注常用的邮箱格式,规则:名称允许汉字、字母、数字,下划线,中划线,域名可以有数字、字母、下划线、中划线组成

汉字的范围是 [\u4e00-\u9fa5],字母的范围是 [a-zA-Z],数字的范围是 [0-9],合起来组成邮箱的名称 ^[A-Za-z0-9-_\u4e00-\u9fa5]+

域名是 [a-zA-Z0-9_-]+,域名后缀可以是多级域名 (\.[a-zA-Z0-9_-]+)+

上面组合起来就是 ^[A-Za-z0-9-_\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$

手机号

手机号的号段可能是会增加的,所以在实际场景中不建议限制得太死了

本正则按照以下规则编写:

  1. 11位数字,以数字 1 开头,即 ^1
  2. 接下来的数字如果是 3,那么 3后面可以跟一个任意数字,即 3\d;如果是 4,那么 4后面可以跟一个5-9之间的数字,即 4[5-9];如果是 5,那么 5后面可以跟一个0-35-9之间的数字,即 5[0-35-9];如果是 6,那么 6后面可以跟 2567 其中一个数字,即 6[2567];如果是 7,那么 7后面可以跟一个0-8之间的数字,即 7[0-8];如果是 8,那么 8后面可以跟一个任意数字,即 8\d;如果是 9,那么 9后面可以跟一个0-35-9之间的数字,即 9[0-35-9]
  3. 最后 8位可以是任意数字

上述三步合起来就是 /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/

数字/货币金额

  1. 支持负数

负号用 -负号,且必须在第一位,即 ^-,再加个 ? 用于表示这个负号可以有也可以没有,即 ^-? 2. 支持千分位分隔(没有也没关系) 如果有千分位,则千分位的后面必然跟着三位数字(否则这个千分号就不应该加了),千分位前面最少一位、最多三位数字,那么可以写成 \d{1,3},\d{3},再精简下,千分位前面的数字其实可以不用限制,因为只要超过三位肯定就有千分位,就会被 \d{3}捕获,所以 \d{1,3} 换成 \d+就行了,因为符合千分位的可以有多个也可能没有,所以写成 \d+(,\d{3})* 3. 如果有小数,则小数点后最多两位 小数点就是 \.,后面跟着最多两位数字 \d{1,2},可能有小数也可能没有,所以整体需要再加个 ? 符号,即 (\.\d{1,2})?

最终规则 /^-?\d+(,\d{3})*(\.\d{1,2})?$/

身份证号

这里只看 2代身份证,18位数字 最后一位是校验位,可能为数字或字符X

  1. 第一位数字在 [1-9] 闭区间内,后面紧跟着5位任意数字,写成 ^[1-9]\d{5}
  2. 再紧跟着的四位数字代表年份(YYYY),因为目前有身份证的人最早是19世纪最晚21世纪,所以这四个数字中的前两位只看是 181920,即 (18|19|20),后两位则可以是任意数字,即 \d{2}
  3. 再紧跟着两位数字是月(MM),月份只可能是 [1-12]闭区间,所以可以写成 (01|02|03|04|05|06|07|08|09|10|11|12),前九位的开头都是 0,第二位是 [1-9] 内的数字,所以简化成 (0[1-9]|10|11|12)
  4. 再紧跟着两位数字是日(DD),范围是 [01-31],可以将这31个数字罗列出来,当然也可以精简下,看成是 [00-09][10-29][30-31]的组合,即 (0[1-9]|[1-2]\d|30|31)
  5. 再紧跟着三位数字是顺序码,即 \d{3}
  6. 最后一位是校验码,可以是数字也可以是 X,即 [\dX]

最终规则 /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|10|11|12)(0[1-9]|[1-2]\d|30|31)\d{3}[\dX]$/

密码校验

最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符

对于 至少1个大写字母 这条规则,这个大写字母的位置是不固定的,只要有就行,如果只有这一条规则的话,正则可以写成 ^\S*[A-Z]+\S*$\S 匹配任意非空白字符,这个规则即代表大写字母的前面、后面可以跟着任意个(包括0个)非空白字符

但除此之外还需要满足最少1个小写字母,1个数字,1个特殊字符,最少6位,你可以将这几条规则都单独写出正则,然后目标字符串跟这5条正则一一匹配,只要全部能匹配上就是对的,写成 js 代码就是:

function match(s: string) {
  return /^\S*[A-Z]+\S*$/.test(s)
    && /^\S*[a-z]+\S*$/.test(s)
    && /^\S*[0-9]+\S*$/.test(s)
    && /^\S*[!@#$%^&*?]+\S*$/.test(s)
    && /^\S*\S{6,}\S*$/.test(s)
}
复制代码

如果就想在一条正则里实现这些校验呢,也是可以的,需要借助 零宽度正预测先行断言(?=exp)),代表 匹配exp前面的位置

有了这个东西,就可以把上面5条规则写到一起去了:/^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*?])\S*$/

这条正则前面后面的 \S* 还是之前的意思不变,中间是提取了5条规则的个性部分,然后通过 ?= 放在一起了,把规则里所有的 ?=去掉行不行?不行,因为如果去掉的话,首先就有顺序上的冲突了,例如上面的规则,如果把所有的 ?=去掉,就代表着 数字必须在大写字母前面,大写字母必须在小写字母前面,特殊字母必须在小写字母前面(除此之外整个正则也是有问题的)

你可以认为 ?= 在匹配的时候会忽略掉其他的 ?=,只关心自己的前面能不能匹配成功,有多个 ?=,则这多个 ?= 都是只关心自己,忽略其他,但整条正则最后的结果是所有 ?= 匹配结果的并集,计算逻辑和上面的 js 是差不多的

提取 HTML 标签数据

要提取的标签字符串类似于 <div class="header-box" name="header">

只是正则话无法完成,需要借助 js

首先,把标签的属性提取出来

这段标签包含标签开始符号、tag、属性字符串、标签结束符号

开始符号是 <,标签名紧跟着开始符号,且只要没遇到空白符就都是标签名,所以连起来就是 <\w+\s*

在开始符号+标签名,和 结束符号的中间,都是属性,结束符号是 >,所以只要没遇到结束符号 >,就认为是属性字符串,用到了反向选择 [^>]*\s*>,合起来就是 /<\w+\s*[^>]*\s*>/,为了能捕获属性字符串,加个小括号,即 /<\w+\s*([^>]*)\s*>/

const str = `<div class="header-box" name="header">`
const mt = str.match(/<\w+\s*([^>]*)\s*>/)
// properties 即 属性字符串,即 class="header-box" name="header"
const properties = mt[1]
复制代码

取到了 class="header-box" name="header" 之后,再对其进行处理,观察规律,每个属性的键值对之间肯定存在空白符,不过却不能通过空白符来直接分割,因为属性值是可以存在空白符的,例如 class="a b"

由于可能是自闭合标签,自闭合标签的最后有没有 / 都是合法的,例如 <hr>hr />都是合法的,所以需要兼容下:/<\w+\s*([^>]*)\s*\/?>/

但属性名是可以确定的,它可能是 = 左边不包括空白符的内容,再次用到反向选择,从左往右匹配,反向选择既不是=也不是不是空白符的内容,即 [^\s=]+

虽然不确定属性值是否包含空白符,但有个是确定的,即属性值必然被引号包围,所以直接取 = 右侧所有引号的内容即可,=".*?"

不过还有个问题,引号不仅可以是单引号还可以是双引号,即 =".*?"='.*?' 都行,如果第一个引号是双引号开头那么对应的第二个引号也必然是双引号,反义单引号亦然,这里需要用到捕获的规则了 =(["']).*?\1\1的意思是这块匹配的内容跟第一捕获组一样,第一捕获组也就是 ["'],如果第一捕获组匹配的是双引号,那么 \1 就代表双引号,否则就代表单引号

至此整个正则为 [^\s=]+=(["']).*?\1

不过还有个问题,属性是可以没有属性值的,例如 <input type="checkbox" checked />,这里 checked 就是可以不写属性值的,所以再兼容下:/[^\s=]+(=(["']).*?\2)?/,又因为希望捕捉属性和属性值,所以给属性和属性值加个小括号:/([^\s=]+)(=(["'])(.*?)\3)?/

上面的代表就可以继续写了

const str = `<div class="header-box" name="header">`
const mt = str.match(/<\w+\s*([^>]*)\s*>/)
// properties 即 属性字符串,即 class="header-box" name="header"
const properties = mt[1]
const mt1 = properties.match(/([^\s=]+)(=(["'])(.*?)\3)?/g)
const obj = {}
if (mt1) {
  mt1.forEach(p => {
    const kv = p.trim().split('=')
    obj[kv[0].trim()] = kv[1].trim().slice(1, -1)
  })
}
// obj => { class: 'header-box', name: 'header' }
复制代码

小结

学会正则的最接途径就是勤加练习,平时遇到可以用正则解决的问题,就尝试着正则解决,或许你一开始写不出来,但可以去网上看看别人是怎么写的,再自己独立写一遍,写得多了自然就会了,没什么诀窍,无非就是对正则规则的熟练掌握罢了

本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/ghau9Orz_XMl_6sNkmV56g

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237270次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8108次阅读
 目录