鸿蒙开发:了解正则表达式

前言

从给出的文本中,按照既定的相关规则,匹配出符合的数据,其中的规则就是正则表达式,使用正则表达式,可以使得我们用简洁的代码就能实现一定复杂的逻辑,比如判断一个邮箱账号是否符合正常的邮箱账号,再比如判断一个手机号是否正常的手机号,等等,正因为有了正则,得以让文本处理起来更加的简单。

当然,也并不是所有的场景我们都需要去使用正则,比如判断两个字符串是否相等,我们使用正则可以判断如下:

TypeScript 复制代码
 private isEqual(a: string, b: string): boolean {
    const regExp = new RegExp(a)
    return regExp.test(b)
  }

直接传递两个相比较的字符串即可。

TypeScript 复制代码
 const isEqual = this.isEqual("AbnerMing", "AbnerMing")
 console.log("===是否相等:" + isEqual)

显然以上的判断是比较冗余的,毕竟我们可以直接判断。

TypeScript 复制代码
 const string1: string = "AbnerMing"
 const string2: string = "AbnerMing"
 console.log("===是否相等:" + (string1 === string2))

同样的场景,比如包含,使用正则也是不如直接使用自带的Api判断方便。

正则判断是否包含某一个字符串:

TypeScript 复制代码
 private isContains(a: string, b: string): boolean {
    const regExp = new RegExp(a, "g")
    return regExp.test(b)
  }

代码判断:

TypeScript 复制代码
 const string1: string = "我是AbnerMing,是一个程序员."
 const string2: string = "一个"
 const isContains = this.isContains(string2, string1)
 console.log("===是否包含:" + isContains)

针对字符串的包含判断,我们也完全可以使用已有的方法进行判断。

比如search方法:

TypeScript 复制代码
const string1: string = "我是AbnerMing,是一个程序员."
const string2: string = "一个"
const isContains = string1.search(string2) != -1
console.log("===是否包含:" + isContains)

比如indexOf方法:

TypeScript 复制代码
const string1: string = "我是AbnerMing,是一个程序员."
const string2: string = "一个"
const isContains = string1.indexOf(string2) != -1
console.log("===是否包含:" + isContains)

所以说,正则表达式固然很好,但是,在实际的开发中,我们也要针对性的选择去用,让它在该有的场景中发挥最大的作用。

了解正则及RegExp

在鸿蒙当中使用正则和TypeScript中如出一辙。

首先需要定义一个正则表达式。

TypeScript 复制代码
const reg = new RegExp('正则表达式');

使用正则表达式

TypeScript 复制代码
const res = reg.test('内容'); 
console.info('===结果:', res);

RegExp对象中,目前有两个方法,一个是test方法,一个是exec方法。

test

此方法,返回一个Boolean,用来查找对应的字符串中是否存在,这个方法是使用最多的,常见的规则判断一般都是使用它。

exec

此方法,用来查找并返回当前的匹配结果,并以数组的形式返回。

显而易见,test方法可以判断,是否符合正则表达式,可以用于判断手机号,邮箱等等是否符合等等场景,而exec方法更侧重于,查找相符合的数据。

常见元字符

元字符‌是一个比较特殊的字符,也是一种特殊规则的文本,主要用于规定前导字符在目标对象中的出现模式,比如匹配数字,匹配字母等等匹配一定规则的文本,常见的元字符如下:

字符匹配

普通字符:直接按照给定的文本进行匹配,比如,一段文本中,匹配到字母"A"的字符。

元字符:元字符上面已经说了,它是具有特殊的含义,例如 \d 匹配任意数字字符,\w 匹配任意字母数字字符,. 匹配任意字符(除了换行符)等。

量词

TypeScript 复制代码
*:匹配前面的模式零次或多次
+:匹配前面的模式一次或多次
?:匹配前面的模式零次或一次
{n}:匹配前面的模式恰好 n 次
{n,}:匹配前面的模式至少 n 次
{n,m}:匹配前面的模式至少 n 次且不超过 m 次

字符类

TypeScript 复制代码
[]:匹配括号内的任意一个字符。例如,[abc] 匹配字符 "a"、"b" 或 "c"
[^ ]:匹配除了括号内的字符以外的任意一个字符。例如,[^abc] 匹配除了字符 "a"、"b" 或 "c" 以外的任意字符

边界匹配

TypeScript 复制代码
^:匹配字符串的开头
$:匹配字符串的结尾
\b:匹配单词边界
\B:匹配非单词边界

分组和捕获

TypeScript 复制代码
( ):用于分组和捕获子表达式
(?: ):用于分组但不捕获子表达式

特殊字符

TypeScript 复制代码
\:转义字符,用于匹配特殊字符本身
.:匹配任意字符(除了换行符)
|:用于指定多个模式的选择

数字

TypeScript 复制代码
数字:^[0-9]*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
带1-2位小数的正数或负数:^(-)?\d+(.\d{1,2})?$
正数、负数、和小数:^(-|+)?\d+(.\d+)?$
有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]){1,3}$ 或 ^+?[1-9][0-9]$
非零的负整数:^-[1-9][]0-9"$ 或 ^-[1-9]\d$
非负整数:^\d+$ 或 ^[1-9]\d*|0$
非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非负浮点数:^\d+(.\d+)?$ 或 1\d*.\d*|0.\d*[1-9]\d*|0?.0+|0$
非正浮点数:^((-\d+(.\d+)?)|(0+(.0+)?))$ 或 ^(-([1-9]\d*.\d*|0.\d*[1-9]\d*))|0?.0+|0$
正浮点数:^[1-9]\d*.\d*|0.\d*[1-9]\d*$ 或 ^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$
负浮点数:^-([1-9]\d*.\d*|0.\d*[1-9]\d*)$ 或 ^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$
浮点数:^(-?\d+)(.\d+)?$ 或 ^-?([1-9]\d*.\d*|0.\d*[1-9]\d*|0?.0+|0)$

校验字符的表达式

TypeScript 复制代码
汉字:^[\u4e00-\u9fa5]{0,}$
英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
长度为3-20的所有字符:^.{3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以输入含有^%&',;=?KaTeX parse error: Expected group after '^' at position 8: "等字符:[^̲%&',;=?\x22]+
禁止输入含有的字符:[^\x22]+

特殊需求表达式

TypeScript 复制代码
Email地址:^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+.)+[\w-]+(/[\w-./?%&=]*)?$
手机号码(可根据目前国内收集号扩展前两位开头号码):^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^((\d{3,4}-)|\d{3.4}-)?\d{7,8}$
国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
15位身份证号:2\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$
18位身份证号:3\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):4[a-zA-Z0-9_]{4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$
日期格式:^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$,例如:2014-10-12
^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\s+(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$,例如:2014-10-12 12:20:00
一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
钱的输入格式:
有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$
这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$
这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
xml文件:^([a-zA-Z]±?)+[a-zA-Z0-9]+.[x|X][m|M][l|L]$
中文字符的正则表达式:[\u4e00-\u9fa5]
双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
空白行的正则表达式:\n\s*\r (可以用来删除空白行)
HTML标记的正则表达式:<(\S*?)[^>]>.?</\1>|<.*? />
腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
IP地址:\d+.\d+.\d+.\d+ (提取IP地址时有用)
IP地址:((?😦?:25[0-5]|2[0-4]\d|[01]?\d?\d).){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))

正确使用正则

应用代码

TypeScript 复制代码
let regex: RegExp = /\s*/g;

建议改法

TypeScript 复制代码
let regexp: RegExp = new RegExp('\s*','g');

原因

如果正则表达式中使用了标志符,需要将其作为new RegExp()的参数。

简单举例

上面的元字符中,已经给出了大量的匹配规则,大家直接套用即可,比如判断是否是一个邮箱,代码如下:

TypeScript 复制代码
 private isEmail(txt: string): boolean {
    const regExp = new RegExp('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$')
    return regExp.test(txt)
  }

相关总结

合理的使用正则表达式,确实在实际的开发中能给我们带来一定的便利,特别是在一些复杂的匹配时,能够带来高效的查找,也能够提高我们的开发效率,但在处理极度复杂任务时可能需要结合其他工具。

在开发中,对于输入的规则是否是RegExp类型,我们可以通过系统提供的isRegExp来进行判断,代码如下:

TypeScript 复制代码
let type = new util.types()
let result = type.isRegExp(new RegExp('abc'))
console.info("=== " + result);
相关推荐
轻口味3 分钟前
【每日学点鸿蒙知识】广告ID、NFC手机充值、CSS支持语法、PC与模拟器交互、SO热更新等
css·智能手机·harmonyos
轻口味25 分钟前
【每日学点鸿蒙知识】无障碍、getLastLocation、蓝牙问题、卡片大小、关系型数据库等
数据库·华为·harmonyos
李游Leo3 小时前
自学记录鸿蒙API 13:Calendar Kit日历功能从学习到实践
学习·华为·harmonyos
别说我什么都不会5 小时前
【OpenHarmony】 鸿蒙 UI开发之DanmakuFlameMaster
harmonyos·arkui
枫叶丹45 小时前
【HarmonyOS之旅】ArkTS语法(三) -> 渲染控制
ui·华为od·华为·华为云·harmonyos
轻口味6 小时前
【每日学点鸿蒙知识】Taro、native层获取文件宽度、位置变化callback、数据迁移、oh_modules说明等
华为·harmonyos·taro
SoraLuna7 小时前
「Mac畅玩鸿蒙与硬件50」UI互动应用篇27 - 水果掉落小游戏
macos·ui·harmonyos
三掌柜6668 小时前
HarmonyOS开发:关于帧动画使用分享
华为·harmonyos
轻口味8 小时前
【每日学点鸿蒙知识】组件对象做参数、2D在子线程中使用、Tabs组件联动、Web组件获取焦点、Text加载藏文
前端·华为·harmonyos