正则

... 2022-12-19 About 7 min

# 正则

什么是正则?正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个字符串是否含有某种子串、将匹配的子串做替换或者从某个字符串中取出符合某个条件的子串等。说白了正则表达式就是处理字符串的,我们可以用它来处理比较复杂的字符串,别小看正则,这哥们的作用可大了(正则表达式(regular expression)是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本。)

关于正则,没有语言限制,前端能用后端也能用,它不属于任何一门语言,但是任何语言都能用它

  • 比较两种声明正则的写法

    1. const regex = /aaa/ 在引擎编译代码时,就会新建正则表达式

    2. const regex = new Regex('aaa') 在运行时新建正则表达式

注:1的效率会比较高,而且书写简单,我的用的时候也用第一种

# 正则的实例方法

# 1. test()

返回Boolean值

const reg = /aa/g
let str = 'abgfahjldf_aa_sdhflgjs_aa_asfas'
reg.lastIndex = 29 // (str.length-2) // 这个地方注意,只有带有g修饰符的时候,这儿可以指定开始位置 ,否则这句等于没有,没有lastIndex话。每次都从0的位置重新开始
reg.test(str) // false
// ps:用于表单提交前验证检查还是比较多的
1
2
3
4
5

# 2. exec()

返回: true--->Array,false---->null

const reg1 = /a/
const reg2 = /b/
let str = '__aaacc'
reg1.exec(str) // [ 'a', index: 0, input: 'aaacc' ] 并不是像我想的二维数组,显然修饰符g在这个地方是没有用的,index表示从什么位置开始的,input表示被检测的字符串
reg2.exec(str) // null
// 而exec实际上的作用更大的是组合的使用
const reg3 = /a(b+)a/
str = 'abba_abbbba'
reg3.exec(str) // [ 'abba', 'bb', index: 0, input: 'abba_abbbba' ]

1
2
3
4
5
6
7
8
9
10

这个还是用的比较少的,要说真的在开发中我用的比较多的还是字符串上面的一些实例方法

# 字符串的实例方法

(注意str,reg的写法位置的不一样,不要搞混)

# 1. match

返回: true--->Array,false---->null

  • 单从返回值来看和exec()还挺像的,但是match可以带修饰符g
let str = 'afhalusdfhasdbnfz'
const reg = /a/g
str.match(reg)  //  [ 'a', 'a', 'a' ] 可以检测字符中某个字符出现过几次
reg.exec(str) // [ 'a', index: 0, input: 'afhalusdfhasdbnfz' ]
1
2
3
4

返回Number 和数组上面的indexof规则一样

'ababab-aaa'.search(/a/) // 0
if(~'ababab-aaa'.search(/a/)){
  console.log('字符串上面有a')
}
1
2
3
4

# 3. replace

在字符串操作的方法的情况比较复杂的情况,也是用的最多的一个

  • 字符串对象的replace方法可以替换匹配的值。它接受两个参数,第一个是正则表达式,表示搜索模式,第二个是替换的内容。
'aaa'.replace(/a/,'b') // 'baa'
'aaa'.replace(/a/g,'b') // 'bbb'
var str = '   #id div.class   '; // 去除dom中的前后的空格
str.replace(/^\s+|\s+$/g,'') 
// ^\s+:^以什么开头,\s空格,+多个;|:或者;\s+$:$以什么结尾
1
2
3
4
5
  • replace中比较麻烦的也是比较有用的替换,replace方法的第二个参数可以使用美元符号$,用来指代所替换的内容。

    • $&:匹配的子字符串。
    • $`:匹配结果前面的文本。
    • $':匹配结果后面的文本。
    • $n:匹配成功的第n组内容,n是从1开始的自然数。(注意组的概念)
    • $$:指代美元符号$。(在这个地方$的转义不一样)
'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1') // "world hello" (\w+)单词,\w文字
'abc'.replace('b', '[$`-$&-$\']')   // "a[a-b-c]c"
1
2
  • replace第二个参数也可以是一个函数
let prices = {
  'p1': '$1.99',
  'p2': '$9.99',
  'p3': '$5.00'
}
let template = '<span id="p1"></span><span id="p2"></span><span id="p3"></span>';
template = template.replace(/(<span id=")(.*?)(">)(<\/span>)/g, (match,$1,$2,$3,$4) =>{
  return $1 + $2 + $3 + prices[$2] + $4
})
// $n表示每个()里面的匹配值
1
2
3
4
5
6
7
8
9
10

# 4. split

返回Array

  • 这哥们其实平常用的很多,在后端数据传输和获取的时候会用到很多eg:
// 获取文件名类型
let filename = 'adfdas.fadf.asdfasdfasf.png'
let type = filename.split('.').pop()
const ids = 'fasdhf;laskjdf;agasdg;fadfasdfa;asdfasdf;asdfasdf'
let arrID = ids.split(';')
1
2
3
4
5
  • 以上就了解了一些方法,检测和替换的写法,其实正则最该去了解还是正则本身怎么写,有一些什么样的字符,或者特殊的字段呢

# 匹配规则

  • 点字符(.)
  • 位置字符(^, $)
    • ^ 表示字符串的开始位置
    • $ 表示字符串的结束位置
let url = 'www.afsdfa.com.cn/?asdfa=324&asdfas=asdf'
console.log(/^((http|https):\/\/)/.test(url) ? 'a'+url : `http://${url}`)
let pathname = 'www.afsdfa.com.cn'
console.log(/\/$/.test(pathname) ? pathname : `${pathname}/`)
1
2
3
4
  • 选择符(|)
/11|22/.test('911') // true 11或者22中的一个
/fred|barney|betty/ // fred,barney,betty中的一个,而不是d或者b,y或者b
1
2
  • 转义符 (\)

    • 需要转义的字符一共12个: ^.[$()|*+?{\

    注: 在用new Rexexp()的时候需要转义两次

    gExp作为构造函数,参数是一个字符串。但是,在字符串内部,反斜杠也是转义字符,所以它会先被反斜杠转义一次,然后再被正则表达式转义一次,因此需要两个反斜杠转义。

# 预定义模式(简写)

  • 数字类
  1. \d 匹配0-9之间的任一数字,相当于[0-9]。( d------>digit )
  2. \D 匹配所有0-9以外的字符,相当于[^0-9]。
let path = 'www.xxxx.com.cn/?icon=static/img/icon-xx/icon1.png'
path.match(/\d/)[0] // '1'
let n = path.replace(/\D/g,'') // '1'
1
2
3
  • 词类
  1. \w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]。( w----->word )
  2. \W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]。
/\s\w*/.exec('hello world') // [" world"]
'hello world'.replace(/(\w+)\s+(\w+)/, '$2 $1') 'world hello'
1
2
  • 空格回车类
  1. \s 匹配空格(包括换行符、制表符、空格符等),相等于[ \t\r\n\v\f]。( s----->space )
  2. \S 匹配非空格的字符,相当于[^ \t\r\n\v\f]。
let str = 'afhjasd ashflajs afdhjas '
str.replace(/\s/,'') // 'afhjasdashflajsafdhjas'
1
2
  • 边界值
  1. \b 匹配词的边界。 ( b----->boundary )
  2. \B 匹配非词边界,即在词的内部。
// \b 的例子
/\bworld/.test('hello world') // true
/\bworld/.test('hello-world') // true
/\bworld/.test('helloworld') // false

// \B 的例子
/\Bworld/.test('hello-world') // false
/\Bworld/.test('helloworld') // true
1
2
3
4
5
6
7
8

# 字符类

  • [xyz]表示:x,y,z之中任选一个匹配
/[abc]/.test('asdjfkhlasj') // true
/[abc]/.test('sdjfkhlsj') // false
1
2
  • 脱字符(^)
/[^abc]/.test('asdjfkhlasj') // false
/[^abc]/.test('sdjfkhlsj') // true
// 如果方括号内的第一个字符是[^],则表示除了字符类之中的字符,其他字符都可以匹配。比如,[^xyz]表示除了x、y、z之外都可以匹配。
// [^]表示非空,也就是说可以匹配所有的字符
1
2
3
4

值得注意的是:脱字符(^)只有在字符类的第一个位置才有特殊含义,否则就是字面含义。

  • 连字符(-)
/a-z/.test('b') // false
/[a-z]/.test('b') // true
// 意思就是连字符联合[]使用的作用是更大的
// 这些简写都是合法的
[0-9.,]
[0-9a-fA-F]
[a-zA-Z0-9]
[0-31]
1
2
3
4
5
6
7
8

# 重复和量词

  1. {n}表示恰好重复n次
  2. 量词符
  • ? 问号表示某个模式出现0次或1次,等同于{0, 1}。
  • * 星号表示某个模式出现0次或多次,等同于{0,}。
  • + 加号表示某个模式出现1次或多次,等同于{1,}。
// ?
let str = 'asdsaadfsg'
/(\w+)a?(\w+)/.test(str) // true
/(\w+)a*(\w+)/.test(str) // true
/(\w+)z+(\w+)/.test(str) // false
//  最好的用法还是和组()或者[]连用
1
2
3
4
5
6

关于还有很多东西可以用但是正则这东西能够了解以上的这些基本的东西,主要是方法的使用和正则怎么写就能够满足工作上面的很多需求的,当然如果还想了解更多的记录了一个链接,写的还挺好的,(贪婪模式,组之类的)

正则相关 (opens new window)

Last update: December 19, 2022 11:58
Contributors: salvatoreliaoxuan , liaoxuan