正则RegExp

128 阅读6分钟

什么是正则表达式

正则表达式是描述字符模式的对象。

  • 正则表达式用于对字符串模式匹配及检索替换,是对 字符串 执行模式匹配的强大工具。
  • 而 String 和 RegExp 都定义了使用正则表达式进行强大的模式匹配和文本检索与替换的函数。
  • 正则表达式主要用来验证客户端的输入数据。可以节约大量的服务器端的系统资源,并且提供更好的用户体 验。

创建正则表达式

1、直接量

语法:Reg = /pattern/modifiers;

var Reg = /box/gi;

2、new RegExp

语法 Reg = new RegExp( pattern , modifiers ) ;

pattern ,modifiers此时是 字符串

var Reg = new RegExp(“box”,”gi”);
  • 何种方法创建都是一样的
  • pattern 模式 模板 ,要匹配的内容
  • modifiers 修饰符

正则表达式用法及区别

1、String中正则表达式方法

方法描述
match(reg)返回RegExp匹配的包含全部 字符串 的数组或 null
search( Reg )返回RegExp匹配字符串首次出现的 位置
replace( Reg,newStr )用 newStr 替换RegExp匹配结果,并返回新字符串
split( Reg )返回字符串按指定RegExp拆分的数组

使用 var str = 'hello';

var Reg = /e/i;

str.match(Reg)

//子组和修饰符
var str = "www.baidu.com?wd=&q=1&type=2"
console.log(str.match(/([^?=&]+)=([^?=&]*)/))
//['wd=', 'wd', '', index: 14, input: 'www.baidu.com?wd=&q=1&type=2', groups: undefined]
console.log(str.match(/([^?=&]+)=([^?=&]*)/g))
//['wd=', 'q=1', 'type=2']
search: 查找字符串中是否有满足条件的内容
  • 语法: 字符串.search(正则)
  • 返回值: 有的话返回开始索引, 没有返回 -1
var reg = /\d{3}/
var str1 = 'hello123'
var str2 = 'hello'
console.log(str1.search(reg))   // 5
console.log(str2.search(reg))   // -1
match: 找到字符串中符合正则条件的内容返回
  • 语法: 字符串.match(正则)

  • 返回值:

    • 没有标识符 g 的时候, 是和 exec 方法一样
    • 有标识符 g 的时候, 是返回一个数组, 里面是匹配到的每一项, 没有匹配到内容是返回的是 null
var reg = /\d{3}/
var str1 = 'hello123world456'
var str2 = 'hello world'
console.log(str1.match(reg))
/*
['123', index: 5, input: 'hello123world456', groups: undefined]
    0: "123"
    groups: undefined
    index: 5
    input: "hello123world456"
    length: 1
*/
console.log(str2.match(reg))    // -1
var reg = /\d{3}/g
var str1 = 'hello123world456'
var str2 = 'hello world'
console.log(str1.match(reg))    // ['123', '456']
console.log(str2.match(reg))    // null
replace: 是将字符串中满足正则条件的字符串替换掉
  • 语法: 字符串.replace(正则, 要替换的字符串)
  • 返回值: 替换后的字符串
var reg = /\d{3}/
var str1 = 'hello123world456'
var str2 = 'hello world'
console.log(str1.replace(reg, '哈哈哈哈'))    // hello哈哈哈哈world456
console.log(str2.replace(reg, '哈哈哈哈'))    // hello world
var reg = /\d{3}/g
var str1 = 'hello123world456'
var str2 = 'hello world'
console.log(str1.replace(reg, '哈哈哈哈'))    // hello哈哈哈哈world哈哈哈哈
console.log(str2.replace(reg, '哈哈哈哈'))    // hello world

2、RegExp对象的方法

方法描述
exec()在字符串中执行匹配搜索,返回首次匹配结果 数组 ,(是有记忆的)
test()在字符串中测试模式匹配,返回 true 或 false

注意区别正则方法和字符串方法使用避免混淆

正则方法:pattern. test( str ) ; 方法的主体是 正则表达式

字符串方法:str. match( pattern ) ;方法的主体是 字符串

修饰符

修饰符用于 执行区分大小写 和 全局 匹配:

  • i 忽略大小 写匹配
  • g 全局匹配 ,默认只匹配第一个元素,就不在进行匹配
  • m 执行 多行匹配
var patt = /pattern/i; //忽略大小写匹配
var patt = /pattern/g; //全局匹配
var patt = /pattern/m; //执行多行匹配

pattern 模式

1、基本匹配

xxx ———————————匹配 xxx 字符

var Reg = /abc/;

x|y|z —————————-匹配 x 或 y 或 z 字符

var Reg = /abc|bac|cba/;

2、[]

[abc] ———————————–匹配abc之中的 任何一个 字符

[^abc] ———————————匹配 非 a 非 b 非 c字符的

到(字符簇)

[0-9]` ———————————匹配`09`之间的数字
`[a-z]` ———————————匹配`小写a至小写z`的字符
`[A-Z]` ———————————匹配`大写A至大写Z`的字符
匹配中文 `[\u4e00-\u9fa5]

还可以组合

var Reg = /hello [0-9a-zA-z]/;

元字符( 转义字符 )

元字符 可以用来指代一类字符的 标识符

转义符 在需要转义元字符前加 \ => \ \ /

.` —————————————–匹配`单个字符`,除了换行和行结束符
`\w`—————————————匹配`单词字符`,`数字`,`_`(下划线)[A-Za-z0-9_]
`\W`—————————————匹配``(`单词字符`和`_`(下划线))
`\d` —————————————匹配`数字`
`\D` —————————————匹配`非数字`
`\s` —————————————匹配空白字符(`空格`)
`\S` —————————————匹配`非空格`字符
`\b` —————————————匹配`单词边界` ( 除了 (字)字母 数字_ 都算单词边界)
`\B` —————————————匹配`非单词边界`
`\n` —————————————匹配`换行符
\n 匹配换行符 \r回车符  \t 匹配制表符 \f 换页符 \v垂直制表符
[\b]回退符backspace 

特殊的转译字符 . \ /

var reg = /./;//匹配.
var reg = /\/;//匹配\
var reg = ///;//匹配/

4、量词

n? ———————————匹配 0个或一个 n的字符串
n* ———————————匹配 0个或多个 字符串( 任意个 )
n+ ———————————匹配 至少一个 n字符串
n{X} ——————————匹配包含 X个n 的序列的字符串(必须挨着)
n{X,Y} ————————–匹配包含 至少X或至多Y个 n的序列的字符串
n{x,} —————————-匹配 至少X个 n的序列字符串
^n ———————————匹配 以n开头 的字符串
n$ ———————————匹配 以n结尾 的字符串
//验证www.xxxx.com/xxx只能是数字或者字母
console.log(/^w{3}.[a-zA-Z0-9]+.com$/.test('ww.ba$idu.com'))

5、贪 婪 惰 性

贪婪: 尽可能多 的匹配

解决 使用非贪婪限定符

惰性: 尽可能少 的匹配

每次捕获都是在下标[0]的位置开始捕获

解决 在正则后添加全局g

前提条件都是要匹配到内容

贪婪惰性
++?
???
**?
{n}{n}?
{n,m}{n,m}?
{n,}{n,}?
console.log('我是,12333'.match(/,\S+/))
//[',12333', index: 2, input: '我是,12333', groups: undefined]
console.log('我是,12333'.match(/,\S+?/))
//[',1', index: 2, input: '我是,12333', groups: undefined]

6、子组(子表达式)

子组:使用 () 小括号,指定一个子表达式后,称之为分组

  • 捕获型
  • 非捕获型
1)、捕获型
var str = 'abcdefg';
var reg = /(abc)d/;//匹配abcd
var val = reg.exec( str);
console.log( val ); //["abcd", "abc", index: 0, input: "abcdefg"]

索引0 为匹配的结果

索引1 为第一个子表达式 匹配结果

index :首次匹配成功的索引值,

input: 匹配目标

字符引用
(pattern)匹配pattern并捕获结果,自动设置组号,是从1开始的正整数\num
1)、非捕获型
  • (?:pattern)
  • (?=pattern) 零宽度正向预言
Windows (?=2000) //匹配windows且后面跟2000

匹配 “Windows2000” 中的 “Windows”

不匹配 “Windows3.1” 中的 “Windows”。

  • (?!pattern) 零宽度负向预言
Windows (?!2000)//匹配windows且后面非2000

匹配 “Windows3.1” 中的 “Windows”

不匹配 “Windows2000” 中的 “Windows”。

console.log('windows2000,windows100'.match(/windows(?=2000)/))
//['windows', index: 0, input: 'windows2000,windows100', groups: undefined]
​
console.log('windows2000,windows100'.match(/windows(?!2000)/))
//['windows', index: 12, input: 'windows2000,windows100', groups: undefined]

string正则方法

捕获

正则方法exec

字符串方法:search match replace

exec 把字符串中符合条件的内容捕获出来

exec 当使用g的时候 有记忆性 直到最后一次输出null 再次打印 重新开始

  • 语法: 正则.exec(字符串)

  • 返回值:

    1. 当原始字符串内没有符合正则规范的片段的时候, 返回值为 null

    2. 当原始字符串内有符合正则规范的判断的时候

      • 返回值一定是一个数组: 数组内的 [0] 是捕获出来的字符串片段

      • 没有 () 没有标识符g

        • 只能获取第一组匹配到的字符串片段
        • 不管匹配多少回, 都是从字符串 [0] 的位置开始检索
      • 有 () 会在返回值数组的 [1] 开始依次是每一个 () 内的单独内容

      • 有 g

        • g 叫做全局标识符
        • 第二次捕获会从第一次捕获的结束位置开始进行检索
        • 直到找不到内容, 返回 null
        • 在下一次捕获的时候, 会从字符串 [0] 开始检索
  • 扩展: 匹配但不捕获

    • 当我们需要使用 () 的一个整体这个作用的时候, 但是又不想单独捕获出来
    • 可以这样书写: (?:)
var str = 'abcdefg';
var reg = /(abc)d/;//匹配abcd
var val = reg.exec( str);
console.log( val ); //["abcd", "abc", index: 0, input: "abcdefg"]

索引0 为捕获的结果

索引1 为第一个子表达式 捕获结果

index :首次匹配成功的索引值,

input: 匹配目标

replace特点 第二个参数

console.log('你好,我好,大家好'.replace(/好/g,
function(item,idx){
    console.log(item,idex)//按replace返回的顺序 
    //item返回的好 idex 返回好的下标
    var str = '开心'
    return str
}                             
))
//$1...$2...$n对应子组($1)($2)
var str = 'abc123'
console.log(str.replace(/(c)|(\d{3})/,'$1o$2a'))//abco123
console.log(str.replace(/(c)|(\d{3})/g,'$1o$2a'))//abco123a//接着replace RegExp.$可以得到上一个replace方法的捕获项
'abc 123'.replace(/([a-z]*)(\d*)/)
console.log(RegExp.$1,RegExp.$2) //RegExp.$1 第一个分组
    
'abc 123'.replace(/([a-z]*).(\d*)/)
console.log(RegExp.$1,RegExp.$2)
​
console.log('abc 123'.replace(/([a-z]*).(\d*)/,'$1+$2'))
console.log(RegExp.$1,RegExp.$2)

预言模式 断言

/*
      先行断言x(?=y)
​
      后行断言(?<=y)x
​
      正向否定查找 x(?!y)
​
      反向否定查找(?<!y)x
​
      ()捕获
      (?:) 非捕获
    */
    //先行断言 x(?=y) 当x后面是y的时候匹配x 不是y的时候不匹配
    console.log(/新年(?=乐)/.test('新年乐'))
​
    //验证整数位是0的小数 0.38 1.27
    console.log(/0(?=.)/.test('1.37'))
    //验证小数 0.38 1.27
    console.log(/\d(?=.)/.test('0.37'))
​
    //后行断言 (?<=y)x 匹配x 当x前面是y的时候
    //验证小数 0.38 1.27
    console.log(/(?<=\d+.)\d/.test('0.37'))
    //获取金额小数位
    console.log('0.123'.match(/(?<=\d+.)(\d+)/))
​
    //整数位大于0的数值 1.23  10 40.5 0.35
    console.log('1.12'.match(/^[1-9]\d*(.\d+)?$/))
    console.log((/^[1-9]\d*(.\d+)?$/).test('1.23'))
    console.log((/^[1-9]\d*(.\d)?$/).test('1.123'))
​
​
    //获取大于1的小数的 .后边的值
    console.log('10.13'.match(/(?<=^[1-9]\d*.)(\d+)/))
​
​
    //正反否定查找 x(?!y) x后边不是y的时候 匹配x
    console.log(/新年(?!乐)/.test('新年快'))//true
    //反向否定查找 (?<!y)x x前边不是y的时候 匹配x
    console.log(/(?<!新年)乐/.test('新年乐'))
    console.log(/(?<!新年)乐/.test('快乐'))

正则 lastIndex陷阱

var arr = [
      'a.jpg',
      'b.jpg',
      'c.jpg',
      'd.jpg'
    ]
    var regExp = /(\S+).jpg/
    for (var key in arr){
      console.log(regExp.test(arr[key]),regExp.lastIndex)
    }
    //var regExp = /(\S+).jpg/ 4*true 0
    //var regExp = /(\S+).jpg/g  true 5 false 0 true 5 false 0
    /*
      正则在g全局修饰下
      当循环列表匹配的时候 lastIndex会干扰结果
      当匹配上的时候 lastIndex 匹配会从字符串最后一位+1 开始技计数
      匹配不到的时候 lastIndex 变为0
​
    */