JS中的正则

作者: 阿龙哟 | 来源:发表于2018-10-12 13:09 被阅读0次

什么是正则?

RegExp: regular expression
按照某种规则去匹配合适条件的字符串


新建正则表达式:
一、字面量形式

var reg = /xyz/

二、使用RegExp构造函数

var reg = new RegExp('xyz')
注意:
1.可以接受第二个参数,全局标志
var reg = new RegExp('xyz','gim')
2.有时需要双重转义字符
var reg = new RegExp('\\wxyx\\w') // \w单词字符

实例属性:

1.修饰符,布尔值,

RegExp.prototype.ignoreCase:返回一个布尔值,表示是否设置了i修饰符。
RegExp.prototype.global:返回一个布尔值,表示是否设置了g修饰符。
RegExp.prototype.multiline:返回一个布尔值,表示是否设置了m修饰符。
注意都是只读的

2.与修饰符无关的属性

(1)RegExp.prototype.lastIndex:返回一个整数,表示下一次开始搜索的位置。该属性可读写,但是只在进行连续搜索时有意义
(2)RegExp.prototype.source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读

实例方法

(1)RegExp.prototype.test()
匹配,有就返回true无就返回false
注意:如果正则表达式带有g修饰符,则每一次test方法都从上一次结束的位置开始向后匹配。

var r = /x/g;
var s = '_x_x';

r.lastIndex // 0
r.test(s) // true

r.lastIndex // 2
r.test(s) // true

r.lastIndex // 4
r.test(s) // false

所以经常会出现同一句代码返回效果却不一样,就是这个lastIndex搞得鬼

(2)RegExp.prototype.exec()
用来返回匹配结果。如果发现匹配,就返回一个数组,成员是匹配成功的子字符串,否则返回null。
注意:如果正则表达式中含有()组匹配,那么返回的结果也会有成功匹配的组成员

var s = '_x_x';
var r = /_(x)/;

r.exec(s) // ["_x", "x"]
image.png

返回的数组还包括以下其他属性:

  • input:整个原字符串。
  • index:整个模式匹配成功的开始位置(从0开始计数)。

如果正则表达式加上g修饰符,则可以使用多次exec方法,下一次搜索的位置从上一次匹配成功结束的位置开始
利用g修饰符允许多次匹配的特点,可以用一个循环完成全部匹配。

var reg = /a/g;
var str = 'abc_abc_abc'

while(true) {
  var match = reg.exec(str);
  if (!match) break;
  console.log('#' + match.index + ':' + match[0]);
}
// #0:a
// #4:a
// #8:a

js字符串与正则表达式相关的方法

  • String.prototype.match():返回一个数组,成员是所有匹配的子字符串。
  • String.prototype.search():按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。
  • String.prototype.replace():按照给定的正则表达式进行替换,返回替换后的字符串。
  • String.prototype.split():按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。

  • match() 方法
    类似于正则对象的exec方法,匹配成功返回一个数组,匹配失败返回null

不同之处在于,match()返回所有成功匹配结果,exec()一次只能返回一个

var s = 'abba';
var r = /a/g;

s.match(r) // ["a", "a"]
r.exec(s) // ["a"]

此外,match()不支持lastIndex属性


  • search()方法

字符串对象的search方法,返回第一个满足条件的匹配结果在整个字符串中的位置。如果没有任何匹配,则返回-1。

'_x_x'.search(/x/)

  • replace()方法
    字符串对象的replace方法可以替换匹配的值。它接受两个参数,第一个是正则表达式,表示搜索模式,第二个是替换的内容。
str.replace(search, replacement)

有g全局标志就全部替换,没有就替换一个

'aaa'.replace('a', 'b') // "baa"
'aaa'.replace(/a/, 'b') // "baa"
'aaa'.replace(/a/g, 'b') // "bbb"
具体实例 模拟实现trim()函数
var str = '  #id div.class  ';
str.replace(/^\s+|\s+$/g, '')
// "#id div.class"

replace方法的第二个参数可以使用美元符号$,用来指代所替换的内容。

$&:匹配的子字符串。
$`:匹配结果前面的文本。
$':匹配结果后面的文本。
$n:匹配成功的第n组内容,n是从1开始      的自然数。
$$:指代美元符号$。
'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')
// "world hello" 适用于组成员变换位置
'abc'.replace('b', '[$`-$&-$\']')
// "a[a-b-c]c"

注意:replace第二个参数还可以是函数,将每个匹配内容替换成函数的返回值

'3 and 5'.replace(/[0-9]+/g, function (match) {
  return 2 * match;
})
// "6 and 10" 将匹配到的3和5都乘了2

function 的参数有:

  • 匹配的字符串
  • 分组内容,如果有3个分组,这部分就有三个参数都传入
  • index 捕捉到的内容在字符串的位置
  • 原字符串
例子
var prices = {
  'p1': '$1.99',
  'p2': '$9.99',
  'p3': '$5.00'
};

var template = '<span id="p1"></span>'
  + '<span id="p2"></span>'
  + '<span id="p3"></span>';

template.replace(
  /(<span id=")(.*?)(">)(<\/span>)/g,
  function(match, $1, $2, $3, $4){
    return $1 + $2 + $3 + prices[$2] + $4;
  }
);
// "<span id="p1">$1.99</span><span id="p2">$9.99</span><span id="p3">$5.00</span>"

分析一下正则表达式
'<span id="p1"></span>'
$1: (<span id=")
$2: (.*?) 就是p1 后面利用$2在哈希中取值prices[$2]
$3:(">)
$4:(</span>)
很经典,四个组匹配$1-$4


split()方法
字符串对象的split方法按照正则规则分割字符串,返回一个由分割后的各个部分组成的数组。

str.split(separator, [limit])
第一个参数是正则表达式,表示分隔规则,第二个参数是返回数组的最大成员数。
// 非正则分隔
'a,  b,c, d'.split(',')
// [ 'a', '  b', 'c', ' d' ]

// 正则分隔,去除多余的空格
'a,  b,c, d'.split(/, */)
// [ 'a', 'b', 'c', 'd' ]

// 指定返回数组的最大成员
'a,  b,c, d'.split(/, */, 2)
[ 'a', 'b' ]

注意

如果正则表达式带有括号,则括号匹配的部分也会作为数组成员返回。

'aaa*a*'.split(/(a*)/)
// [ '', 'aaa', '*', 'a', '*' ]

匹配规则

1.字面量字符和元字符

  • “字面量字符”:也叫原意文本字符
    /dog/ 就是表示d、o、g三个字母连在一起

  • 元字符

'* + ? $ ^ . | \ ( ) { } [ ]' 需要用\转义

(1).字符

点字符(.)匹配除回车(\r)、换行(\n) 、行分隔符(\u2028)和段分隔符(\u2029)以外的所有字符

(2) 位置字符

^ 开始 $ 结束

(3) 或字符 |

2.特殊字符

特殊字符 含义
\cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字、
[\b] 匹配退格键(U+0008),不要与\b混淆。
\n 匹配换行键。
\r 匹配回车键。
\t 匹配制表符 tab(U+0009)。
\v 匹配垂直制表符(U+000B)。
\f 匹配换页符(U+000C)。
\0 匹配null字符(U+0000)。
\xhh 匹配一个以两位十六进制数(\x00-\xFF)表示的字符。
\uhhhh 匹配一个以四位十六进制数(\u0000-\uFFFF)表示的 Unicode 字符。

3.字符类
使用元字符[]来构造一类
[abc] 就是把a、b、c、归为一类

脱字符(^)

如果方括号内的第一个字符是[^],
则表示除了字符类之中的字符,其他字符都可以匹配。比如,[^xyz]表示除了x、y、z之外都可以匹配。

/[^abc]/.test('hello world') // true
/[^abc]/.test('bbc') // false

上面代码中,字符串hello world不包含字母a、b、c中的任一个,所以返回true;字符串bbc不包含a、b、c以外的字母,所以返回false。

如果方括号内没有其他字符,即只有[^],就表示匹配一切字符,其中包括换行符。相比之下,点号作为元字符(.)是不包括换行符的。

var s = 'Please yes\nmake my day!';

s.match(/yes.*day/) // null
s.match(/yes[^]*day/) // [ 'yes\nmake my day']

上面代码中,字符串s含有一个换行符,点号不包括换行符,所以第一个正则表达式匹配失败;第二个正则表达式[^]包含一切字符,所以匹配成功。

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

字符类去反^ [^abc] 非a或b或c的内容

范围类 - [a-z] a到z任意字符
中间可以连写[a-zA-Z]

4.预定义模式

预定义字符 含义
\d 匹配0-9之间的任一数字,相当于[0-9]。
\D 匹配所有0-9以外的字符,相当于[^0-9]。
\w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]。
\W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]。
\s 匹配空格(包括换行符、制表符、空格符等),相等于[ \t\r\n\v\f]。
\S 匹配非空格的字符,相当于[^ \t\r\n\v\f]。
\b 匹配词的边界。
\B 匹配非词边界,即在词的内部。

5.重复类+量词

符号 含义
{n} 出现n次
{n,m} 出现n到m次
{n,} 至少出现n次
出现零次或1次(<=1)
+ 出现一次或多次(>=1)
* 出现零次或者多次(任意次)

6.贪婪模式和非贪婪模式
默认情况下是贪婪模式,会最大可能匹配

var s = 'aaa';
s.match(/a+/) // ["aaa"]
上面代码中,模式是/a+/,表示匹配1个a或多个a,那么到底会匹配几个a呢?因为默认是贪婪模式,会一直匹配到字符a不出现为止,所以匹配结果是3个a。

如果想将贪婪模式改为非贪婪模式,可以在量词符后面加一个问号。

var s = 'aaa';
s.match(/a+?/) // ["a"]
上面代码中,模式结尾添加了一个问号/a+?/,这时就改为非贪婪模式,一旦条件满足,就不再往下匹配。
非贪婪模式 含义
+? 表示某个模式出现1次或多次,匹配时采用非贪婪模式。
*? 表示某个模式出现0次或多次,匹配时采用非贪婪模式。
?? 表格某个模式出现0次或1次,匹配时采用非贪婪模式。

7.修饰符

修饰符 含义
g修饰符 表示全局匹配(global),加上它以后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换。
i修饰符 以后表示忽略大小写(ignorecase)。
m修饰符 表示多行模式(multiline),会修改^和$的行为

8.组匹配
正则表达式的括号表示分组匹配,括号中的模式可以用来匹配分组的内容。

var m = 'abcabc'.match(/(.)b(.)/);
m// ['abc', 'a', 'c']

注意,使用组匹配时,不宜同时使用g修饰符,否则match方法不会捕获分组的内容。

var m = 'abcabc'.match(/(.)b(.)/g);
m // ['abc', 'abc']

正向引用:正则表达式内部,还可以用\n引用括号匹配的内容

/(.)b(.)\1b\2/.test("abcabc")
// true \1引用第一个组(.)\2引用第二个组(.)

反向引用 $1 $2

'abc'.replace(/(a)b(c)/,'$2b$1')
//"cba" 

非捕获组:
(?:x)称为非捕获组(Non-capturing group),表示不返回该组匹配的内容,即匹配的结果中不计入这个括号。

var m = 'abc'.match(/(?:.)b(.)/);
m // ["abc", "c"] 第一个组设置成了非捕获组了,所以不在返回的数组里

前瞻

先行断言(正向前瞻):reg(?=y)
先行否定断言(负向前瞻):x(?!y)

就好像你站在原地,向前眺望:
正向前瞻型分组 - 你前方是什么东西吗?
负向前瞻型分组 - 你前方不是什么东西吗?

太拗口了,我喜欢称之为肯定表达式与否定表达式。先举个正向前瞻的例子:

var reg = /kid is a (?=doubi)/

reg.test('kid is a doubi')  // true
reg.test('kid is a shabi')  // false
kid is a 后面跟着什么?如果是doubi才能匹配成功。

而负向前瞻则刚好相反:

var reg = /kid is a (?!doubi)/

reg.test('kid is a doubi')  // false
reg.test('kid is a shabi')  // true

如果前瞻型分组也不会捕获值。那么它与非捕获型的区别是什么?看例子:

var reg, str = "kid is a doubi"

reg = /(kid is a (?:doubi))/
reg.test(str)
RegExp.$1  // kid is a doubi

reg = /(kid is a (?=doubi))/
reg.test(str)
RegExp.$1  // kis is a

可见,非捕获型分组匹配到的串,仍会被外层的捕获型分组捕获到,但前瞻型却不会。当你需要参考后面的值,又不想连它一起捕获时,前瞻型分组就派上用场了。

最后,JS不支持后瞻型分组。

相关文章

  • 火星文RegExp

    正则基本不陌生 JS中通过RegExp来创建 正则在JS中非常的成熟 创建 可以使用perl的语法var exp...

  • JS中的正则

    什么是正则? RegExp: regular expression按照某种规则去匹配合适条件的字符串 新建正则表达...

  • JS中的正则

    正则:就是一个规则,用来处理字符串的一个规则(对象数据类型)处理:1、匹配:判断一个字符串是否符合我们指定的规则 ...

  • JavaScript的几个高级应用

    正则表达式在JS中的应用 RegExp内置对象详解 MDN-JS-RegExp 中文文档有几个正则符号需要特别注意...

  • 正则表达式笔记(1)

    正则对象(引用数据类型) 正则:是一种字符串处理规则JS中的正则,一种引用数据类型(RegExp)正则的编写方式字...

  • Js正则表达式

    一、Js正则表达式概述 正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象...

  • 正则初解

    title: js验证常用正则表达式date: 2017-03-03 验证 正则表达式 本文介绍js验证常用的正则...

  • 2018-09-15

    正则表达式的区别 JS中语法: /匹配对象的模式/

  • 正则表达式

    正则表达式介绍: //正则表达式不是js中的独有功能//其他的一些语言中也有正则的实现方式,当我们在查看关于正则的...

  • JS正则表达式的骚操作

    参考资料 《JS正则表达式的分组匹配》《正则表达式之捕获组/非捕获组介绍》《正则表达式中(?:pattern)、(...

网友评论

    本文标题:JS中的正则

    本文链接:https://www.haomeiwen.com/subject/pxwwaftx.html