正则基础语法

介绍

正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。这些模式被用于 RegExpexectest 方法, 以及 StringmatchmatchAllreplacesearchsplit 方法。

正则对象

要使用正则表达式,就必须在程序创建\color{#c7254e}{正则对象}

其中,有两种创建方式

正则对象

  • 1. 隐式创建
const reg = /\d/gi  // 匹配模式/匹配标志

// 动态正则匹配
const regSubstring = '0123456789'.substring(4, 7)
const reg = eval(`/${regSubstring}/g`)
  • 2. 直接实例化
/**
 * @param {string | RegExp} RegExp 匹配模式
 * @param {string} mode 匹配标志
 */
const reg = new RegExp('abcd', 'gi')

// 动态正则匹配
let name1 = "xxx";
const reg1 = new RegExp(name) // /xxx/

let name2 = "xxx\\d";
const reg2 = new RegExp(name) // /xxx\d/
  • 3. 区别
const reg = /\d/gi

// 如果直接实例化,那么像"\d"这样的字符,需要转义"\\d"
const reg = new RegExp("\\d","gi")
匹配标志
  • global: 全局搜索。保留最后一个匹配项的索引,允许迭代搜索。
  • case insensitive: 忽略大小写。 使整个表达式不区分大小写。
  • multiline: 多行。 起点/终点锚点(^/$)将与一行的起点/终点匹配。
  • single line (dotall): Dotall。Dot (.)将匹配任何字符,包括换行符。\color{#e7c002}{警告:并非所有浏览器都支持`dotall`功能。}
  • unicode: Unicode。 启用\x{FFFFF}Unicode转义。\color{#e7c002}{警告:并非所有浏览器都支持“ unicode”功能。}
  • sticky: sticky。 该表达式只会从其lastIndex位置进行匹配,并忽略全局(g)标志(如果已设置)。\color{#e7c002}{警告:并非所有浏览器都支持“粘性”功能}
如果使用正则对象

在js中,使用正则对象主要有两种用法:

RegExp类

  • test:方法执行一个检索,用来查看正则表达式与指定的字符串是否匹配。返回 truefalse

参数:用来与正则表达式匹配的字符串
返回值:如果正则表达式与指定的字符串匹配 ,返回true;否则false

// 语法: regexObj.test(str)

const str = 'hello world!'
let result = /^hello/.test(str)
console.log(result) // true

注意⚠️ : 当设置全局标志的正则使用test()

如果正则表达式设置了全局标志,test()的执行会改变正则表达式 lastIndex属性。连续的执行test()方法,后续的执行将会从 lastIndex 处开始匹配字符串,exec()同样改变正则本身的 lastIndex属性值)

  • lastIndex: 是正则表达式的一个可读可写的整型属性,用来指定下一次匹配的起始索引。
const regex = /foo/g;
console.log(regex.lastIndex) // 0
regex.test('foo') // true

console.log(regex.lastIndex) // 3
regex.test('foo') // false
  • exec: 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null

参数:要匹配正则表达式的字符串
返回值:如果匹配成功,exec() 方法返回一个数组(包含额外的属性 indexinput ,参见下方表格),并更新正则表达式对象的 lastIndex 属性。完全匹配成功的文本将作为返回数组的第一项,从第二项起,后续每项都对应正则表达式内捕获括号里匹配成功的文本。

// 语法: regexObj.exec(str)

// 匹配 "quick brown" 后跟 "jumps",忽略中间的字符
// 记住 "brown" 跟 "jumps"
// Ignore case 忽略大小写

const reg = /quick\s(brown).+?(jumps)/ig
let result = re.exec('The Quick Brown Fox Jumps Over The Lazy Dog')
// 结果:
// [
//   0: "Quick Brown Fox Jumps",
//   1: "Brown",
//   2: "Jumps",
//   groups: undefined,
//   index: 4,
//   input: "The Quick Brown Fox Jumps Over The Lazy Dog",
//   length: 3
// ]

下表列出这个脚本的返回值:

对象 属性/索引 描述 例子
result [0] 匹配的全部字符串 Quick Brown Fox Jumps
result [1],...[n] 括号中的分组捕获 [1] = Brownㅤㅤㅤㅤㅤㅤㅤ[2] = Jumps
result index 匹配到的字符位于原始字符串的基于0的索引值 4
result input 原始字符串 The Quick Brown Fox Jumps Over The Lazy Dog
reg lastIndex 下一次匹配开始的位置 25
reg ignoreCase 是否使用了 "i" 标记使正则匹配忽略大小写 true
reg global 是否使用了 "g" 标记来进行全局的匹配. true
reg multiline 是否使用了 "m" 标记使正则工作在多行模式(也就是,^$ 可以匹配字符串中每一行的开始和结束(行是由 \n\r 分割的),而不只是整个输入字符串的最开始和最末尾处。) false
reg source 正则匹配的字符串 quick\s(brown).+?(jumps)


String类

  • search: 匹配符合匹配模式的字符串出现的位置。

参数:一个正则表达式对象。如果传入一个非正则表达式对象 regexp,则会使用 new RegExp(regexp) 隐式地将其转换为正则表达式对象。
返回值:如果匹配成功,则 search() 返回正则表达式在字符串中首次匹配项的索引;否则,返回 -1

// 语法: str.search(regexp)

let str = "hey JudE";
const reg = /[A-Z]/g;
const reg1 = /[.]/g;

console.log(str.search(reg)) // 4, 这是第一个大写字母“J”的索引
console.log(str.search(reg1)) // -1 找不到 “.” 点标点
  • match: 方法检索返回一个字符串匹配正则表达式的结果。

参数:一个正则表达式对象

  • 如果传入一个非正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp 。如果你没有给出任何参数并直接使用match() 方法 ,你将会得到一 个包含空字符串的 Array :[""]

返回值:

  • 如果使用g标志,则将返回与完整正则表达式匹配的所有结果,但不会返回捕获组。
  • 如果未使用g标志,则仅返回第一个完整匹配及其相关的捕获组(Array)。 在这种情况下,返回的项目将具有如下所述的其他属性。
  • 如果正则表达式不包含 g标志,str.match() 将返回与 RegExp.exec() 相同的结果。
// 语法: str.match(regexp)

let str = 'For more information, see Chapter 3.4.5.1';
const reg = /see (chapter \d+(\.\d)*)/i;
let found = str.match(reg);

console.log(found);

// [
//   0: 'see Chapter 3.4.5.1',
//   1: 'Chapter 3.4.5.1',
//   2: '.1',
//   groups: undefined,
//   index: 22,
//   input: 'For more information, see Chapter 3.4.5.1'
// ]

// 'see Chapter 3.4.5.1' 是整个匹配。
// 'Chapter 3.4.5.1' 被'(chapter \d+(\.\d)*)'捕获。
// '.1' 是被'(\.\d)'捕获的最后一个值。
// 'index' 属性(22) 是整个匹配从零开始的索引。
// 'input' 属性是被解析的原始字符串。

  • replace: 使用指定的内容替换匹配模式的字符串。

参数

  • regexp (pattern):一个RegExp对象或者其字面量。该正则所匹配的内容会被第二个参数的返回值替换掉
  • substr (pattern):一个将被 newSubStr 替换的 字符串。其被视为一整个字符串,而不是一个正则表达式。仅第一个匹配项会被替换。
  • newSubStr (replacement):用于替换掉第一个参数在原字符串中的匹配部分的字符串。该字符串中可以内插一些特殊的变量名
  • function (replacement): 一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。

返回值:一个部分或全部匹配由替代模式所取代的新的字符串。

// 语法: str.replace(regexp|substr, newSubStr|function)

// newSubStr: 必需。一个字符串值。规定了替换文本或生成替换文本的函数。
// 下面是 特殊的变量名

// $1、$2、...、$99: 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本
// $$: 插入一个 '$'
// $&: 与 regexp 相匹配的子串
// $`: 位于匹配子串左侧的文本
// $': 位于匹配子串右侧的文本
// $$: 直接量符号

let str = 'aaa-bbb-ccc'
str.replace('aaa', 'ddd') // ddd-bbb-ccc
str.replace(/ddd/, 'aaa') // aaa-bbb-ccc
str.replace(/(aaa)-/, '$1~') // aaa~bbb-ccc
str.replace(/\a/g, (item, index, str) => {
 console.log(item, index, str) // a 0 aaa-bbb-ccc
 return index // 最后返回结果:"012-bbb-ccc"
})
  • split: 方法使用指定的分隔符字符串将一个String对象分割成子字符串数组,以一个指定的分割字串来决定每个拆分的位置。

参数:

  • separator:指定表示每个拆分应发生的点的字符串。separator 可以是一个字符串正则表达式。 如果纯文本分隔符包含多个字符,则必须找到整个字符串来表示分割点。如果在str中省略或不出现分隔符,则返回的数组包含一个由整个字符串组成的元素。如果分隔符为空字符串,则将str原字符串中每个字符的数组形式返回。

  • limit:一个整数,限定返回的分割片段数量。当提供此参数时,split 方法会在指定分隔符的每次出现时分割该字符串,但在限制条目已放入数组时停止。如果在达到指定限制之前达到字符串的末尾,它可能仍然包含少于限制的条目。新数组中不返回剩下的文本。

返回值:返回源字符串以分隔符出现位置分隔而成的一个 Array

// 例子1: separator 是字符串
let myString1 = 'Hello World. How are you doing?'

console.log(myString1.split(' '))
// ["Hello", "World.", "How", "are", "you", "doing?"]
console.log(myString1.split(' ', 3))
// ["Hello", "World.", "How"]

// 例子2: separator 是正则
let myString2 = 'Hello 1 word. Sentence number 2.'
let splits = myString2.split(/(\d)/)

console.log(myString2.split(/\d/))
// ["Hello ", " word. Sentence number ", "."]
console.log(myString2.split(/(\d)/))
// ["Hello ", "1", " word. Sentence number ", "2", "."]  如果正则中有子表达式,那么配置的 子表达式 也会被匹配进去

子表达式()

let str = '12312312php2545fxx'
// 例如:/(\d)php/中的"(\d)"就是一个子表达式

捕获

在正则匹配模式中,子表达式匹配到的内容会被系统捕获至系统的缓冲区中,我们称之为捕获

var str = '12312312php2545fxx'
// 例如:/(\d)php/    //2php 2就被捕获至系统 **1号** 的缓冲区中

反向引用

捕获之后,可以在匹配模式中使用\n(n:数字)来引用系统的第n号缓冲区内容

let str = '12312312php2545fxx'
// 例如:/(\d)php\1/    //匹配的就是2php2了,\1是引用了1号缓冲区中的2,因为php前面的是2
  • 例子
// + 匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}
// * 匹配前面的子表达式任意次。例如,zo*能匹配“z”,也能匹配“zo”以及“zoo”。*等价于{0,}。
// \w 匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集
// \W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”
// . 匹配除“\n”和"\r"之外的任何单个字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式。
let str1 = 'qewqsjava111javadssphp222php9uiyu33owds'
const reg1 = /(\W+)\d\d\d\1/gi;
str.match(reg1)
// 结果java111java, php222php

const reg2 = /(\w+)\d\d\d\1/gi;
let result;
while (result=reg2.exec(str)) {
    alert(result)
}
// result[0]:java111java     这是匹配到的内容
// result[1]:java    这里是第一个子表达式的值

// result[0]:php222php
// result[1]:php

// 查找连续相同的四个数字,如:1208
const reg = /\d\d\d\d/gi  //或者var reg = /\d{3}/gi
// 查找连续相同的四个数字,如:1111
const reg = /\d\1\1\1/gi
// 查找数字,如:1221,3443
const reg = /(\d)(\d)\2\1/gi  //1111这样的也会匹配到
// 查找字符,如:AABB,TTMM
const reg = /(\w)\1(\w)\2/gi
// 查找连续相同的四个数字或四个字符
const reg = /(\w)\1\1\1/gi
// 再一个字符串,查找一对html标记以及中间的内容
let str2 = iqeos<div>标签</div>adasdda<p>100.00p</p>qewq
const reg = /<(\w+)>.*<\/\1>/gi

一般情况下,后面的内容要求与前面的一致,就会用的子表达式、捕获、反向引用

  • exec方法和match方法的比较:
    exec方法是RegExp类下的方法
    matchString下的方法
    match方法直接返回一个数组
    exec方法需要循环反复调用
    如果有子表达式,exec方法将子表达式的捕获结果放到数字对应的元素中

正则语法

正则表达式是由普通字符(例如字符 a-z ,0-9)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

普通字符:a-z,0-9 等等
特殊字符(元字符):\d \s \w . * 等等

  • (1)限定符

    • 限定符可以指定正则表达式的一个给定组件必须要出现多少次才能满足匹配

    •  *      匹配前面的组件零次或者多次
      
    •  +      匹配前面的组件一次或者多次
      
    •  ?      匹配前面的组件零次或者一次
      
    •  {n}    匹配确定的 n 次
      
    •  {n,}   至少匹配 n 次
      
    •  {n,m}  最少匹配 n 次且最低匹配 m 次
      
    • * , + , ? 也可以用下面的方式表示

      • * {0,}
      • + {1,}
      • ? {0,1}
  • (2)字符匹配符

    • 字符匹配符用于匹配某个或某些字符

      带有[]的叫字符簇,一个簇表示一个字符

      [a-z]:表示 a-z 任意一个字符
      [A-Z]:表示 A-Z 任意一个字符
      [0-9]:表示0-9任意一个字符
      [0-9a-z]:表示 0-9 a-z 任意一个字符
      [0-9a-zA-Z]:表示 0-9 a-z A-Z任意一个字符
      [abcd]:表示a或b或c或d 任意一个字符
      [1234]:表示1或2或3或4 任意一个字符
      [^a-z]:表示除了 a-z 以外的任意字符
      [^0-9]:表示除了0-9以外的任意字符
      [^abcd]:表示除了1或2或3或4 以外的任意字符
      \d:匹配一个数字字符 [0-9]
      \D:匹配一个非数字字符 [^0-9]
      \w:匹配包括下划线的任意单词字符[0-9a-zA-Z_]
      \W:匹配任何非单词字符 [^0-9a-zA-Z_]
      \s:匹配任何空白字符 (空格、制表符、换行符)
      \S:匹配任何非空白字符
      .:匹配除 “\n” 之外的任何单个字符

  • (3)定位符
    定位符可以将一个正则表达式固定在一行的开始或者结束。也可以创建只在单词内或只在单词的开始或者结尾处出现的正则表达式
    ^:匹配字符串的开始位置
    $:匹配字符串的结束位置
    \b:匹配单词的开始位置或结束位置
    \B:匹配不是单词开头位置或结束位置
    注意:在字符簇的^跟不表达式里^是不同意思的

    • 例如
      [^x]:匹配除了x以外的任意字符
      [^aeiou]:匹配除了aeiou这几个字母以外的任意字符
      const reg = /^a/    //表示匹配第一个位置a
      const reg1 = /\Ba\B/    //表示匹配前后都不是单词边界的a 
      
    • 例子:验证年龄
      const reg = /^/d/d  $/g
      
  • (4)转义符
    \:用于匹配某些特殊字符

  • (5)选择匹配符
    |:可以匹配多个规则

    • 例子:
    const str = 'hello Java,hello JavaScript'
    const reg = /hello (JavaScript|Java)/g
    console.log(str.match(reg)) // ["hello Java", "hello JavaScript"]
    
  • (6)关于正则表达式的几种特殊用法

名称 正则 描述
(?:x)非捕获组(Non-capturing group) /(?:\d)/.exec('2019') 使用了()捕获,不会出现在捕获中
(?=)正向前瞻 (Negative lookahead) 也叫先行断言 x(?=y) 匹配x仅仅当x后面跟着y这种叫做 先行断言
x(?!y)****(Positive lookahead)

(?=)正向前瞻:

let str = 'xxx好人,xxx好好人'
const reg = /xxx(?=好人)/gi
console.log(str.match(reg)) // ["xxx"](xxx好人的xxx)

贪婪匹配原则

  • 例如:\d{3,5} //匹配最少3个最多5个的数子
const str = 'jau123123122wjqei78781h123ui131213aa'
const reg = /\d{3,5}/gi
console.log(str.match(reg))
// 结果:["12312", "3122", "78781", "123", "13121"]

上面这个例子中,既匹配三个,也可以匹配五个,那么,正则表达式中会自动匹配最多的那一种,这在正则中叫贪婪匹配原则
在表达式的后面使用" ? ",表示非贪婪匹配原则,但是不会去匹配4个数字或者5个数字了

  • 例如
const str = '123456q1234e12345'
const reg = /\d{3,5}?/gi
console.log(str.match(reg))
//结果: ["123", "456", "123", "123"]
  • 例子:替换重复的字
let str = '我..是是.是.一一个个..好好.好人.人人'
let reg = /\.+/g
str = str.replace(reg,'') // "我是是是一一个个好好好人人人"
reg = /(.)\1+/g
str = str.replace(reg,'$1') // "我是一个好人"
// $1是1号缓冲区内容替换重复的内容
  • 例子:验证ip是否有效
// 规则
// 例子 1.1.1.1
// 0-255
// 第一个段不能是0
// 不能以0开头 如:011
const ip = '192.168.0.32'
const reg = /^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/g
if (reg.test(ip)) {
    console.log('合法')
} else{
    console.log('不合法')
}
  • 例子:验证邮箱是否有效
const email = '347904341@cctv.admin.pl'
const reg = /^[\w\.]+@(\w+\.)+[a-z]{2,5}$/gi
if (reg.test(email)) {
    console.log('合法')
} else{
    console.log('不合法')
}
  • 例子: 密码强度校验,密码6-20位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符
const reg = /^(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[.!@#$%^&? ])\S{6,20}$/
reg.test('123Aa!') // true
reg.test('45678901234567890Aa!') // true
reg.test('456789012345678901Aa!') // false
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 前言 最先接触编程的知识是在大学里面,大学里面学了一些基础的知识,c语言,java语言,单片机的汇编语言等;大学毕...
    oceanfive阅读 3,055评论 0 7
  • 初衷:看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印...
    DCbryant阅读 3,996评论 0 20
  • --------------------------正则的作用--------------------------...
    G_whk阅读 615评论 1 5
  • 1,正则表达式的作用:匹配一个字符串中的一些内容 2,声明和使用: 1)构造函数 var reg=new RegE...
    WDL_1a39阅读 729评论 0 1
  • 打造一款机器学习产品是多方面的复杂任务。下面是机器学习专家在工作中需要做的事: 理解语境 找准能从机器学习中受益的...
    Koap阅读 270评论 0 0