正则表达式 初学篇

2020-05-30  本文已影响0人  幻之国2012

正则表达式 初学篇

正则表达式 虽说不常用, 但是每当用到的时候基本都要去问百度, 得到的答案可能又不完全适用, 想自己改, 单独看每个字符都很熟悉, 但是连在一起看, (。>д<)p 这都是神马鬼~

所以是时候学习了解下了, 当你用一行正则表达式完美解决几个嵌套判断才能实现的功能时, 它不香吗?

举个简单常见的 🌰 :【手机号 验证】

enmm... 非正则的方法 可能是

  const telNum = '13012341234'
  const telAry = telNum.split('')
  const val1 = telAry.length === 11 ? true : false
  const val2 = telAry[0] === '1' ? true : false
  const val3 = ['3','4','5','7','8'].indexOf(telAry[1]) !== -1 ? true : false
  const result = (val1 && val2 && val3) ? '手机号格式正确' : '手机号格式错误'

那么 正则的方法: /^1[34578][0-9]{9}$/

  const telNum = '13012341234'
  const regex = /^1[34578][0-9]{9}$/
  const result = regex.test(telNum) ? '手机号格式正确' : '手机号格式错误'

然后我们简单分析下 regex, 可以分成下面几个小块

^1      //  ^: 表示需要匹配的字符串的开始位置; ^1 表示字符串以1开始
[34578] // []: 标记一个表达式的开始 [ 与 结束 ]; 此处可以理解为 (3 || 4 || 5 || 7 || 8)
[0-9]   //     同上; 此处可以理解为 (0 || 1 || 2 ... || 8 || 9)
{9}     // {}: 限定符, 匹配它前面的表达式出现的次数; 例如: [1]{3} => [1][1][1]
$       //  $: 表示需要匹配的字符串结束位置; 9$/ 表示需要匹配以 9 结尾的字符串

这时候有的童鞋可能会问, 这个 ^ 怎么读啊? (;¬_¬) 呵呵~, 别问, 问就是我也不知道~
所以去查了下, 百度百科给的说法是 ^ : 中文尚无通用名称,可以是乘方、插入符号、插入符、脱字符号等;英文称为caret (英语发音:/ˈkærət/); 不过这些不是重点, 只要知道它是干什么用的就好了

非常简单的小小练习题 1:
(单选)下面哪个正则表达式可以完全匹配字符串 str='11223 11222 11233 11232'
A: /^11[23]{3}/g
B: /[11]{1}[23]{3}/g
C: /1{2}[23]{3}$/g
D: /[123]{5}/g
小拓展: /g => g:表示全局查找, 匹配尽可能多的数据, 如果没有 g ,只匹配第一个符合要求的值

  var str='11223 11222 11233 11232'
  var reg = ''
  console.log(str.match(reg));

常用元字符 及 基本用法

元字符是构造正则表达式的一种基本元素。

接下来介绍下正则表达式的常用元字符以及基本用法, 其实网上随随便便就能查到, 但是很多都把它们列在了一起, 乍一看很多的样子, 这里把一些常用的区分开了, 可能会好记一些(对我而言)

定位符:   ^   $   \b   \B

定位符 表示你能够将正则表达式固定到行首或行尾

^  匹配输入字符串的开始位置; 当该符号在 [] 方括号表达式中使用时, 表示不接受该方括号表达式中的字符集合

  const str = 'the boy is ten years old'
  const reg1 = /^the/g  // 匹配输出 ["The"]
  const reg2 = /^boy/g  // 匹配输出 null
  const reg3 = /[^oes]/g// 匹配输出 ["T", "h", " ", "b", "y", " ", "i", " ", "t", "n", " ", "y", "a", "r", " ", "l", "d"]

$  匹配输入字符串的结尾位置

  const str = 'The boy is ten years old'
  const reg1 = /old$/g  // 匹配输出 ["old"]
  const reg2 = /years$/g// 匹配输出 null

\b  匹配一个单词边界, 即字与空格间的位置

  const str = 'this is sister island persist consist his axis'
  const reg1 = /\w*is\b/g // 匹配输出 ["this", "is", "his", "axis"]
  const reg2 = /\bis\w*/g // 匹配输出 ["is", "island"]
  const reg3 = /\bis\b/g  // 匹配输出 ["is"]
  const reg4 = /\w*is\w*/g// 可以匹配到全部字符
  这里的 \w 与 * 后面会有相关介绍, 这里使用是为了能更好的说明 \b 用法
  // \w: 匹配包括下划线的任何单词字符
  // * : 限定符, 匹配其前面的子表达式出现 0次 或 多次

\B  非单词边界匹配

  const str = 'this is sister island persist consist his axis'
  const reg1 = /\Bis\B/g  //输出 this is sISter island persISt consISt his axis
  const reg2 = /\Bis/g    //输出 thIS is sISter island persISt consISt hIS axIS
  const reg3 = /is\B/g    //输出 this is sISter ISland persISt consISt his axis
  console.log(str.replace(reg1, 'IS')); // 将全部符合要求的 is 替换为 IS

限定符:   *   +   ?   {n}   {n,}   {n,m}

限定符用来指定它之前的子表达式出现的次数, 目前共有6种

* 匹配其前面的子表达式出现   0次   或   多次

  const str = 'ABC AAB AAA BBB ABB BAA CCC ACC'
  const reg1 = /AB*/g // 匹配  1个A 0个或多个B 的字符串
  //输出 ["AB", "A", "AB", "A", "A", "A", "ABB", "A", "A", "A"]

+ 匹配其前面的子表达式出现   1次   或   多次

  const str = 'ABC AAB AAA BBB ABB BAA CCC ACC'
  const reg1 = /AB+/g // 匹配 1个A 1个或多个B 的字符串
  //输出 ["AB", "AB", "ABB"]

? 匹配其前面的子表达式出现 0次 或 1次

  const str = 'ABC AAB AAA BBB ABB BAA CCC ACC'
  const reg1 = /AB?/g // 匹配 1个A 0个或1个B 的字符串
  //输出 ["AB", "A", "AB", "A", "A", "A", "AB", "A", "A", "A"]

{n} 匹配其前面的子表达式出现 n次, n 非负整数;

  const str = 'ABC AAB AAA BBB ABB BAA CCC ACC'
  const reg1 = /AB{2}/g // 匹配 1个A 2个B 的字符串
  //输出 ["ABB"]

{n,} 匹配其前面的子表达式至少出现 n次; n 非负整数;

  AB{0,} = AB*
  AB{1,} = AB+

{n,m} 匹配其前面的子表达式至少出现 n 次,最多出现 m 次; n & m 非负整数; {n,m} 之间不能有空格;

  AB{0,1} = AB?
  // {n,m} 之间不能有空格  {0, 1}=>❌   { 0,1 }=>❌

【注】:不能将限定符与定位符连接使用, 错误示例:  ^*   \b*

其他特殊字符:

. 匹配除换行符   \n   之外的任何 单字符

\ 转义特殊字符; 例:  \&nbsp;匹配字符 &nbsp;

| 指明两项之间的一个选择

  const str = 'AAAAA ABACB ABACA ABBAA ACACA ACBEA ADABC'
  const reg1 = /A(A|B|C)\w{3}/g  // 匹配 AA*** 或者 AB*** 或者 AC*** 形式的字符串
  // ["AAAAA", "ABACB", "ABACA", "ABBAA", "ACACA", "ACBEA"]
  const reg2 = /A(C|BA)\w*/g  // 匹配 AC 开头 或者 ABA 开头 形式的字符串
  // ["ABACB", "ABACA", "ACACA", "ACBEA"]
  const reg3 = /\b(AA\w*|AC\w*)/g  // 匹配 AA*** 或者 AC*** 形式的字符串
  // ["AAAAA", "ACACA", "ACBEA"]
  //  如果去掉 \b 匹配结果为: ["AAAAA", "ACB", "ACA", "AA", "ACACA", "ACBEA"]
  在书写正则表达式的时候, 一定要严格判断, 防止修改到自己预期之外的字符数据

() 标记一个子表达式的开始和结束位置

  const str = 'AAAAA ABACB ABACA ABBAA ACACA ACBEA'
  const reg1 = /A(A|B)A(C|E)\w*/g
  // 匹配 以A开始, 第2个字符是 A 或者 B, 第3个字符是 A, 第4个字符是 C 或者 E 的字符
  // ["ABACB", "ABACA"]

[] 标记一个中括号表达式的开始和结束位置; [] 内的每一个字符 (连字符 - 与 ^ 除外) 都会当做参数做判断

  const str = 'AAA Abc ABB A-C A^B ACT AZZ A=T A5K'
  const reg1 = /A[AB]\w*/g
  // 匹配 AA* 或者 AB* 形式的字符串; [AB] = (A|B)
  // 输出 ["AAA", "ABB"]
  const reg2 = /A[A-D0-9]\w*/g
  // 匹配 A(A|B|C|D)* 或 A(0 到 9 的数字)* 形式的字符串
  // 输出 ["AAA", "ABB", "ACT", "A5K"]
  const reg3 = /A[A--D]\w*/g
  // ❌这是一个错误的表达式;
  const reg4 = /A[-a-z]\w*/g
  // 连字符 出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头或者结尾,则只能表示连字符本身
  // ["Abc", "A-C"]
  const reg5 = /A[^^A-F]\w*/g
  // ^ 出现在 [] 的开始位置, 表示匹配任何不在指定范围内的任意字符, 出现在其他位置匹配其本身
  // ["A Abc", "A-C", "AZZ", "A=T", "A5K"], 如果不想匹配 "A Abc" 这样的数据需要怎么修改? (提问 1)

{} 标记限定符表达式的开始和结束位置

  const reg1 = /AB{2}/g // 匹配 ABB 字符
  const reg2 = /(AB){2}/g // 匹配 ABAB 字符
  {} 的使用格式只有三种 {n} {n,} {n,m}

\d  匹配一个数字字符。等价于[0-9]

\D  匹配一个非数字字符。等价于[^0-9]

\w  匹配包括下划线的任何单词字符, 类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。

  const str = 'Ab 你好 #@_(*&^!~10/;⊙'
  const reg1 = /\w/g
  // 输出 ["A", "b", "_", "1", "0"]

\W  匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。

  const str = 'Ab 你好 #@_(*&^!~10/;⊙'
  const reg1 = /\W/g
  // [" ", "你", "好", " ", "#", "@", "(", "*", "&", "^", "!", "~", "/", ";", "⊙"]

\s  匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]

\S  匹配任何可见字符。等价于[^ \f\n\r\t\v]。

\f  匹配一个换页符。等价于\x0c和\cL。

\n  匹配一个换行符。等价于\x0a和\cJ。

\r  匹配一个回车符。等价于\x0d和\cM。

正则表达式模式修饰符

/g 全局标记, 表示该表达式将用来在输入字符串中查找所有可能的匹配,返回的结果可以是多个。如果不加/g最多只会匹配一个

  const str = 'the girl, the boy'
  const reg1 = /the/  // 只能匹配到 第一个 the
  const reg2 = /the/g // 可以匹配到全部 the

/i  表示匹配的时候不区分大小写

 const str='IS is Is iS'
 const reg1 = /is/g  // 只能匹配到 is
 const reg2 = /is/gi // 可以匹配到全部 全局匹配不区分大小写

/m  表示多行匹配。什么是多行匹配呢?就是匹配换行符两端的潜在匹配。影响正则中的^$符号

/s  与/m相对,单行模式匹配。

/e  可执行模式,此为PHP专有参数,例如preg_replace函数。

/x  忽略空白模式。

简单的小小练习题 2:
(单选)能够完全匹配字符串 "(010)-62661617" 和字符串 "010****8099"的正则表达式是
A: /(?\d{3})?-?\d{8}/g
B: /[0-9(-)]\d/g
C: /[0-9*()-]+/g
D: /[(]?\d[)-]\d*/g

到这里的时候, 你应该就可以写一些简单的正则用来判断处理字符串了,
然后有的童鞋可能还会问, 如果想修改别人的正则表达式从何下手?或者说看到一个很长很长的正则怎么去理解什么意思?

例如: /[1-8]\d{5}((18|19|20))?\d{2}[0-1]\d[0-3]\d{4}(\d|x)?/

其实从左到右分块按顺序转义就好了

  [1-8]   // 一个 1-8 的数字
  \d{5}   // 5 个 0-9 的数字
  ((18|19|20))? // 无 或者 18 或者 19 或者 20
  \d{2}   // 2 个 0-9 的数字
  [0-1]   // 0 或者 1
  \d      // 一个 0-9 的数字
  [0-3]   // 0 或者 1 或者 2 或者 3
  \d{4}   // 4 个 0-9 的数字
  (\d|x)? // 无 或者 1个0-9的数字 或者 X

正则表达式 的运算符优先级

运算符优先级: 高 --> 低

\  转义符 最高

(),(?:),(?=),[]  圆括号 方括号

*,+,?,{n},{n,},{n,m}  限定符

^,$,\任何字符  定位点和序列

|  或者

正则初学篇 就到此结束吧!

非常感谢大家百忙之中看完本片文档, 如果哪里有错误的地方请大家指出, 如果哪里说得不好不够详细的, 请大家多做自我批评~

如果后期有机会 可能会在深入学习下, 也会对此篇进行完善, 毕竟还有很多正则知识在这里没有介绍到;
(*^_^*) 再次感谢! 有缘再见~


简单的小小练习题答案:
题1: D
题2: C

提问 答案:
1: /\bA[^^A-F]\w*/g

工具推荐

在线工具(菜鸟在线工具,可以编译正则表达式,并查看匹配结果,还给出了一些常用的表达式写法)

REGEXPER(一个让正则表达式图形化的工具, 据说转义图形后更加简单易懂)

正则元字符列表

上一篇下一篇

猜你喜欢

热点阅读