正则表达式

正则表达式

1. 概述

(1)正则表达式:(Regular Expression)用于匹配规律规则的表达式,正则表达式最初是科学家对人类神经系统的工作原理的早期研究,现在在编程语言中有广泛的应用。

(2)正则表通常被用来检索、替换那些符合某个模式(规则)的文本

(3)正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串” ,这个“规则字符串”用来表达对字符串的一种过滤逻辑

2. 正则表达式的作用

(1)给定的字符串是否符合正则表达式的过滤逻辑(匹配)

(2)可以通过正则表达式,从字符串中获取我们想要的特定部分(提取)

(3)强大的字符串替换能力(替换)

3. 正则表达式的测试

在线测试正则:https://c.runoob.com/front-end/854

正则表达式语法

1. 语法

(1)在 JavaScript 中,正则表达式也是对象,是一种索引类型。

(2)使用一个正则表达式字面量是最简单的方式。两个 / 是正则表达式的定界符。

(3)可以通过下面两种方法创建一个正则表达式:

  • 使用一个正则表达式字面量,var reg = /abc/; (常用)
  • 正则表达式字面量在脚本加载后编译。若你的正则表达式是常量,使用这种方式可以获得更好的性能。

(4)调用 RegExp 对象的构造函数, var re = new RegExp("abc");

2. 相关正则方法

(1)字符串的方法:

  • split():根据匹配字符串切割父字符串
  • match():使用正则表达式与字符串相比较,返回一个包含匹配结果的数组。
  • search():对正则表达式或指定字符串进行搜索,返回第一个出现的匹配项的下标。
  • replace():用正则表达式和字符串直接比较,然后用新的子串来替换被匹配的子串。

(2)正则表达式方法:

  • exec():在目标字符串中执行一次正则匹配操作。
  • test():测试当前正则是否能匹配目标字符串

3. String: split

(1)根据匹配字符串切割父字符串

(2)eg: 根据空格切割字符串:‘aa bbb c dd eeeeee’

  • aa bbb c dd eeeeee'.split(/\s+/)
  • => [“aa” , “bbb” , “c” , “dd” , “eeeeee”]
// split 方法:分割字符串,成为一个数组
var str = "aa bbb c dd eeeeee";
// 使用一个空格字符进行的精确分割
//   var arr = str.split(" ");
// 使用正则表达式可以进行模糊匹配分割
var arr = str.split(/\s+/);
console.log(arr); // ["aa" , "bbb" , "c" , "dd" , "eeeeee"] 
// 需求:根据字母a切割字符串
var str2 = "bbaacaaaadddaeeeeeaaf";
var arr2 = str2.split(/a+/);
console.log(arr2); // ["bb", "c", "ddd", "eeeee", "f"]

4. String: search

(1)寻找匹配字符串在父字符串中位置

(2)eg:在‘abcdefg’中寻找‘cd’位置

  • 'abcdefg'.search(/cd/)
  • => 2

(3)找不到返回 -1

// search 方法:查询子串在父字符串中出现的位置
var str = "abcdefg";
console.log(str.search("cd")); // 2
console.log(str.search("cdf")); // -1
console.log(str.search(/ef/)); // 4
console.log(str.search(/eff/)); // -1
// 寻找‘o o’位置
var str = "aaaa o o bbb aa";
console.log(str.search(/o\s+o/));  // 5

5. String: match

(1)在父字符串中寻找匹配字符串

(2)在 ‘abbcccbbbbbddbbbdabbb’ 中查询重复 ‘b’ 字符串

  • 'abbcccbbbbbddbbbdabbb'.match(/b+/g)
  • => [“bb” , “bbbbb” , “bbb” , “bbb”]
// match 方法:在父字符串中去匹配符合的子字符串,将结果输出到数组中
var str = "abbcccbbbbbddbbbdabbb";
// var arr = str.match(/b+/); // 在匹配到第一个之后就结束
var arr = str.match(/b+/g); // 如果有全局修饰符 g,会在找到所有匹配的字符串后结束
console.log(arr);  // ["bb" , "bbbbb" , "bbb" , "bbb"]
// 找寻所有‘o o’字符
var str1 = "aaaa o o bbb o   o aaa";
var arr1 = str1.match(/o\s+o/g);
console.log(arr1); // ["o o", "o   o"]

6. String: replace

(1)替换父字符串中匹配字符串

(2)eg:将’www.hello.com’替换成’www.byebye.com’

  • 'www.hello.com'.replace(/hello/, 'byebye')
  • => “www.byebye.com”
// replace 方法:替换字符串的指定部分,返回值是一个新的替换后的字符串,原始字符串不受影响
// 第一个参数:替换前的;第二个参数:替换后的
var str = "www.hello.com";
var str1 = str.replace(/hello/, "byebye");
console.log(str);  // www.hello.com
console.log(str1);  // www.byebye.com
// 过滤字符串中空格
var str = "aa b c d e f ";
var str1 = str.replace(/\s+/g, "");
console.log(str);  // aa b c d e f 
console.log(str1);  // aabcdef

7. RegExp: exec

(1)在字符串中寻找匹配字符串,该方法比其他正则方法或字符串方法支持的更复杂

(2)eg:在’aaaabccccbacabc’中查找’abc’字符串

  • var result = /abc/.exec('aaaabccccbacabc')
  • result => [“abc”]
  • result.index => 3
// exec 方法:查找匹配的字符串,输出到数组中
// 不论有没有全局修饰符,都只会在找到第一个之后停止
var str = "aaaabccccbacabc";
var reg = /abc/;
var arr = reg.exec(str);
console.log(arr); // ["abc"] 
console.log(arr.index); // 3
// 匹配["o 0 0 o"]
var str = "ooooo 0 0 ooooooooooo";
var reg = /o\s0\s0\so/;
var arr = reg.exec(str);
console.log(arr); // ["o 0 0 o"]

8. RegExp: test

(1)检测字符串是否匹配正则表达式

(2)eg:判断’aaddccddabcddeeddfff’是否包含’abc’字符串

  • /abc/.test('aaddccddabcddeeddfff')
  • => true
// test 方法:检测字符串中是否满足正则表达式的匹配规则,返回值是布尔值
var reg = /abc/;
console.log(reg.test("aaddccddabcddeeddfff")); // true
// 检测'a bc'和'abc'是否包含空格
var reg = /\s/;
console.log(reg.test("ab c")); // true
console.log(reg.test("abc")); // false

正则表达式的组成

1. 正则表达式的组成

(1)由一些普通字符和一些特殊字符(又叫元字符–metacharacters)组成。普通字符包括大小写 的字母和数字,而元字符则具有特殊的含义。

(2)特殊字符:javascript 中常用特殊字符有 ( ) [ ] { } \ ^ $ | ? * + .

(3)若想匹配这类字符必须用转移符号 \ 如:\( , ^ , \\

(4)预定义特殊字符:

  • \t—— /\t/ —— 制表符
  • \n—— /\n/ —— 回车符
  • \f—— /\f/ —— 换页符
  • \b—— /\b/ —— 空格
// 普通字符组成的正则
var reg = /abc/;
// 表示正则匹配时,需要进行精确匹配,必须包含a、b、c三个字符,并且顺序不能颠倒,而且要连续书写
console.log(reg.test("adgfgnkldgadfabc")); // true
// 特殊字符,匹配字符串中对应的普通的符号字符时,需要进行转义
var reg = /a\*/; // 匹配 a后边紧跟一个*号
console.log(reg.test("dghdfva*")); // true
// 预定义特殊字符
// 一些特殊的字符串不能在正则中直接书写相同的符号,所以正则中提供了一些替换写法
var reg = /\t/;
// 在加载过程中,浏览器识别 tab 符有一些兼容的问题
console.log(reg.test("    ")); // false

// 匹配所有空白字符可以用 \s
var reg = /\s/;
console.log(reg.test("    ")); // true
// \n 表示的是回车符
// 如果写 "" 双引号按回车换行会报错,语法会出错
// 此处可以写反引号 ``,反引号可以包含换行符
var str = `adsggh
asdgfh`;
console.log(/\n/.test(str)); // true

正则的术语

1. 字符集

  • 符集:使用 [] 表示的可能的字符的集合,集合内部可以排列多个匹配字符串的可能性,整个字符集需要匹配的是字符串中的一个字符
  • []:字符串中的一个字符,多选一的效果,有一个满足就算匹配成功

(1)简单类

  • 正则的多个字符对应一个字符,我们可以用 [] 把它们括起来,让 [] 这个整体对应一个字符[abc]
  • eg:o[usb]t——obt、ost、out
// 简单类:多个可能匹配的字符连续书写在一起,只要其中一个匹配成功即可
var reg = /[abc]/;
console.log(reg.test("eeeea")); // true

(2)范围类

  • 有时匹配的东西过多,而且类型又相同,全部输入太麻烦,我们可以在中间加了个横线。[a-z]、[0-9]、[A-Z]
  • eg:id[0-9]——id0、id5
// 范围类:将匹配同一类型且连续在一起的字符写到集合中,中间使用 - 连接
// var reg = /[0-9]/; // 匹配 0-9
// var reg = /[a-z]/;  // 匹配 a-z
var reg = /[A-Q]/; // 匹配 A-Q
console.log(reg.test("AASD133")); // true

(3)负向类

  • [] 前面加个元字符进行取反,表示匹配不能为括号里面的字符。[^a]
  • eg:o[^0-9]t——oat、o?t、o t
// 负向类:取反的意思,不包含字符集内部书写的字符
var reg = /[^A-Q]/;
console.log(reg.test("A")); // false 若是只有 A-Q 之间的字符就是 false
console.log(reg.test("A1234WEES")); // true 只要包含A-Q以外的字符就是 true

(4)组合类

  • 允许用中括号匹配不同类型的单个字符。[0-9a-b]
  • eg:o[0-9a-b]t——oat、o?t、o
// 组合类:单一类型或者简单类不能匹配所有结果,可以将多个写法连在一起书写
// 特殊的:如果数字、大写字母、小写字母,按照这种顺序写的完整的范围,可以缩写
var reg = /[0-9a-z]/; // 即 0-9、A-Z、a-z,缩写为0-z
var reg = /[0-9A-Z]/; // 即 0-9、A-Z,缩写为 0-Z
var reg = /[0-z]/; // 即0-9、A-Z、a-z
console.log(reg.test("A7")); // true

2. 修饰符

(1)g 修饰符用于执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。

  • '12a34b56c78d90e'.match(/\d+/) => [“12”]
  • '12a34b56c78d90e'.match(/\d+/g) => [“12”, “34”, “56”, “78”, “90”]
// g 修饰符:可以实现全局查找
var str = "aabbbkkBBlsbbkjhkbkjh";
var reg = /b+/g;
console.log(str.match(reg)); // ["bbb", "bb", "b"]

(2)i 修饰符用于执行对大小写不敏感的匹配。

  • 'aabAAcAa'.match(/aa/g) => [“aa”]
  • 'aabAAcAa'.match(/aa/gi) => [“aa”, “AA”, “Aa”]
// i 修饰符:字母大小写可以不敏感,a 可以匹配 a 或 A
var str = "aabbbkkBBlsbbkjhkbkjh";
var reg = /A/gi;
console.log(str.match(reg)); // ["a", "a"]

3. 边界

(1)^

  • 开头,注意不能紧跟于左中括号的后面
  • /^hello/.test('hello javascript') => true
  • /^javascript/.test('hello javascript') => false

(2)$

  • 结尾
  • /javascript\$/.test('hello javascript') => true
  • /hello$/.test('hello javascript') => fals
// 边界
// ^ 表示限制开头,后面的正则内容匹配的结果必须出现在字符串开始
var str = "hello Javascript";
console.log(/^hello/.test(str)); // true
console.log(/^lhello/.test(str)); // false

// $ 表示限制结尾,前面的正则内容匹配的结果必须出现在字符串结尾
console.log(/script$/.test(str)); // true
console.log(/scripthaha$/.test(str)); // false

// 实际应用中,会同时限制开头和结尾
console.log(/^hello\s+Javascript$/.test(str)); // true

4. 预定义类

正则表达式

注:digital——数字、space——空白、word——单词

// 非回车非换行字符
console.log(/^.+$/.test("asd123AAF*&")); // true
console.log(
  /^.+$/.test(`asd123
  AAF*&`)
); // false
// \d 数字字符、\D 非数字字符
console.log(/^\d+$/.test("12344890")); // true
console.log(/^\d+$/.test("12344aa890")); // false
console.log(/^\D+$/.test("asfSSD&*")); // true
console.log(/^\D+$/.test("asfSSD&*23")); // false
// \s 空白字符、\S 非空白字符
console.log(
  /^\s+$/.test(`
`)
); // true
console.log(
  /^\s+$/.test(`1
`)
); // false
console.log(/^\S+$/.test("Aa2*")); // true
console.log(/^\S+$/.test("Aa  2*")); // false
// \w 单词字符、\W 非单词字符
console.log(/^\w+$/.test("asd09_A")); // true
console.log(/^\w+$/.test("as*&d09_A")); // false
console.log(/^\W+$/.test("$*&#-+")); // true
console.log(/^\W+$/.test("$*&as-#+")); // false

5. 量词

正则表达式

// {n} 硬性量词,对应前面的内容必须在字符串中出现 n 次连续
var reg = /^\d{5}$/;
console.log(reg.test("1783")); // false
console.log(reg.test("17834")); // true
console.log(reg.test("178345")); // false
// {n,m} 软性量词,对应前面的内容必须在字符串中出现 n-m 次连续
var reg = /^\d{5,7}$/;
console.log(reg.test("1234")); // false
console.log(reg.test("12345")); // true
console.log(reg.test("1234567")); // true
console.log(reg.test("12345678")); // false
// {n,} 软性量词,对应前面的内容必须在字符串中出现至少 n 次连续
var reg = /^\d{5,}$/;
console.log(reg.test("1234")); // false
console.log(reg.test("12345")); // true
console.log(reg.test("123456783465478")); // true
//  ? 软性量词,等价于{0,1},表示前面的内容出现 0 次或 1 次
var reg = /^\d?$/;
console.log(reg.test("")); // true
console.log(reg.test("1")); // true
console.log(reg.test("12345")); // false
//  * 软性量词,等价于{0,},表示前面的内容出现 0 次或 任意次
var reg = /^\d*$/;
console.log(reg.test("")); // true
console.log(reg.test("1")); // true
console.log(reg.test("12345")); // true
//  + 软性量词,等价于{1,},表示前面的内容出现 1 次或 以上
var reg = /^\d+$/;
console.log(reg.test("")); // false
console.log(reg.test("1")); // true
console.log(reg.test("12345")); // false

6. 分组

(1)虽然量词的出现,能帮助我们处理一排密紧密相连的同类型字符。但这是不够的,我们用中括号表示范围内选择,大括号表示重复次数。

(2)如果想获取重复多个字符,我们就要用小括号进行分组 了。

  • /(bye){2}/.test('byebye') => true
  • /(bye){2}/.test('bye') => false
// 分组
var reg = /^(bye){2}$/;
console.log(reg.test("byebye")); // true
console.log(reg.test("bbyyee")); // false

7. 或操作符

可以使用竖线(|)字符表示或者的关系。

  • /a|bcd/:匹配 a 或 bcd 字符。
  • /(ab)+|(cd)+/:匹配出现一次或多次的 ab 或者 cd
// 或操作符 |
var reg = /^a|bcd$/; // 匹配时,要么匹配以 a 开头的,要么匹配以 bcd 结尾的
console.log(reg.test("cbcd")); // true
console.log(reg.test("cbcde")); // false
console.log(reg.test("abcd")); // true

// 如果想在正则中,在两个规则之间只能选其中一个,不能包含其他的开头结尾,需要将或运算放到分组里
var reg = /^(ab|cd)$/;
console.log(reg.test("abcd")); //false
console.log(reg.test("ab")); // true
console.log(reg.test("cd")); // true

8. 分组的反向引用

反向引用标识是对正则表达式中的匹配组捕获的子字符串进行编号,通过“\编号(在表达式中)” , “$编号(在表达式外)”进行引用。从1开始计数

  • /(bye)\1/.test('byebye') => true
  • /(bye)\1/.test('bye') => false
  • '123*456'.replace(/(\d{3})\*(\d{3})/, '$2*$1') => “456*123”
  • '123*456'.replace(/(\d{3})\*(\d{3})/, function (match, $1, $2) { return $2 + '*' + $1 }) => "456*123
// 正则中通过分组匹配到的字符串,会被进行编号,从 1 开始
// 在正则内部可以通过 \1 方式,去对字符串进行反向引用
console.log(/^([a-z]{3})\1$/.test("byebye")); // true ()得到bye,\1也得到bye,所以相当于匹配byebye
console.log(/^([a-z]{3})\1$/.test("byelie")); // false

// 正则表达式以外通过 $1,进行字符串的引用
var str = "123*456".replace(/^(\d{3})\*(\d{3})$/, "$2 * $1");
console.log(str); // 456 * 123
// 第二个参数可以是一个函数
var str1 = "123*456".replace(
  /^(\d{3})\*(\d{3})$/,
  function (match, $1, $2) {
    return $1 * 3 + "/" + $2 * 2;
  }
);
console.log(str1); // 369/912

9. 中文字符

匹配中文:[\u4e00-\u9fa5]

  • /[\u4e00-\u9fa5]+/.test('中文内容') => true
  • /[\u4e00-\u9fa5]+/.test('aaa') => false
// 匹配中文字符
var reg = /^[\u4e00-\u9fa5]+$/;
console.log(reg.test("只有中文的文字内容")); // true
console.log(reg.test("只有中文的文字 内容")); // false
console.log(reg.test("只有中文的文字a内容")); // false

var reg = /^[a-z\u4e00-\u9fa5]+$/;
console.log(reg.test("只有中文的文字内容")); // true
console.log(reg.test("只有中文的文字 内容")); // false
console.log(reg.test("只有中文的文字a内容")); // true

测试

// 1、SE出现0次或1次,0-9的12位数字
var reg = /^(SE)?[0-9]{12}$/;
console.log(reg.test("123456789123")); // true
console.log(reg.test("SI123456789123")); // false
console.log(reg.test("1234567890")); //false
console.log(reg.test("ESX1234567Y")); // false

// 2、要么是1-9的一位数,要么是非0开头的两位数,要么是非0开头的三位数
var reg = /^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$/;
console.log(reg.test("010")); // false
console.log(reg.test("0020")); //false
console.log(reg.test("124")); // true
console.log(reg.test("30000")); // false

// 3、把匹配到的第一个 A 替换为 a
var s = "The AAA is a good AAAA.";
var r = /A/;
var ns = s.replace(r, "a");
console.log(ns); // The aAA is a good AAAA.

// 4、0-5的数字出现0次或1次,之后是0-9的1位数
var reg = /^[0-5]?[0-9]$/;
console.log(reg.test("99")); // false
console.log(reg.test("009")); // false
console.log(reg.test("0009")); // false
console.log(reg.test("10")); // true
上一篇:Android NDK开发篇(一):新版NDK环境搭建(免Cygwin,超级快)


下一篇:【JavaScript】正则表达式