资讯专栏INFORMATION COLUMN

Regexp对象二

VPointer / 1310人阅读

摘要:需要特别注意的是,如果使用方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。匹配一个以两位十六进制数表示的字符。相比之下,点号作为元字符是不包括换行符的。星号表示某个模式出现次或多次,等同于。

匹配规则
字面量字符和元字符
转义符
特殊字符
字符类
预定义模式
重复类
量词符
贪婪模式
修饰符
组匹配

1.匹配规则
2.字面量字符和元字符
除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思/abc/
(1)点字符(.)
点字符(.)匹配除回车(r)、换行(n) 、行分隔符(u2028)和段分隔符(u2029)以外的所有字符
(2)位置字符
^ 表示字符串的开始位置
$ 表示字符串的结束位置
(3)选择符(|)
竖线符号(|)在正则表达式中表示“或关系”(OR),即cat|dog表示匹配cat或dog
使用原括号()
/a( |t)b/.test("atb") // true
上面代码指的是,a和b之间有一个空格或者一个制表符。

3.转义符
正则表达式中那些有特殊含义的元字符
反斜杠转义的,一共有12个字符:^、.、[、$、(、)、|、*、+、?、{和。
需要特别注意的是,如果使用RegExp方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。

4.特殊字符
正则表达式对一些不能打印的特殊字符,提供了表达方法。

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 字符。

5.字符类[]
(1)脱字符(^)
1表示除了x、y、z之外都可以匹配。

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

var s = "Please yesnmake my day!";

s.match(/yes.*day/) // null
s.match(/yes[^]*day/) // [ "yesnmake my

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

表示字符的连续范围。比如,[abc]可以写成[a-c],
最后一个字符类[1-31],不代表1到31,只代表1到3。

另外,不要过分使用连字符,设定一个很大的范围,否则很可能选中意料之外的字符。最典型的例子就是[A-z],表面上它是选中从大写的A到小写的z之间52个字母,但是由于在 ASCII 编码之中,大写字母与小写字母之间还有其他字符,结果就会出现意料之外的结果。

/[A-z]/.test("") // true

6.预定义模式
预定义模式指的是某些常见模式的简写方式。

d 匹配0-9之间的任一数字,相当于[0-9]。
D 匹配所有0-9以外的字符,相当于2
w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]。
W 除所有字母、数字和下划线以外的字符,相当于3
s 匹配空格(包括换行符、制表符、空格符等),相等于[ trnvf]。
S 匹配非空格的字符,相当于4
b 匹配词的边界。
B 匹配非词边界,即在词的内部
// s 的例子
/sw*/.exec("hello world") // [" world"]

// 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
上面代码中,s表示空格,所以匹配结果会包括空格。b表示词的边界,所以world的词首必须独立(词尾是否独立未指定),才会匹配。同理,B表示非词的边界,只有world的词首不独立,才会匹配

通常,正则表达式遇到换行符(n)就会停止匹配。

var html = "Hellonworld!";

/.*/.exec(html)[0]
// "Hello"
上面代码中,字符串html包含一个换行符,结果点字符(.)不匹配换行符,导致匹配结果可能不符合原意。这时使用s字符类,就能包括换行符。

var html = "Hellonworld!";

/[Ss]*/.exec(html)[0]
// "Hellonworld!"
上面代码中,[Ss]指代一切字符

7.重复类
使用大括号({})表示。{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。
/lo{2}k/.test("look") // true
/lo{2,5}k/.test("looook") // true

8.量词符
? 问号表示某个模式出现0次或1次,等同于{0, 1}。

星号表示某个模式出现0次或多次,等同于{0,}。

加号表示某个模式出现1次或多次,等同于{1,}

// t 出现0次或1次
/t?est/.test("test") // true
/t?est/.test("est") // true

// t 出现1次或多次
/t+est/.test("test") // true
/t+est/.test("ttest") // true
/t+est/.test("est") // false

// t 出现0次或多次
/t*est/.test("test") // true
/t*est/.test("ttest") // true
/t*est/.test("tttest") // true
/t*est/.test("est") // true

9.贪婪模式
默认情况有多少匹配多少。+多+1个 非贪婪+10?0

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

贪婪模式改为非贪婪模式
除了非贪婪模式的加号,还有非贪婪模式的星号(*)和非贪婪模式的问号(?)。
var s = "aaa";
s.match(/a+?/) // ["a"]

+?:表示某个模式出现1次或多次,匹配时采用非贪婪模式。
*?:表示某个模式出现0次或多次,匹配时采用非贪婪模式。
??:表格某个模式出现0次或1次,匹配时采用非贪婪模式
"abb".match(/ab*b/) // ["abb"]
"abb".match(/ab*?b/) // ["ab"]

"abb".match(/ab?b/) // ["abb"]
"abb".match(/ab??b/) // ["ab"]

10.修饰符
修饰符(modifier)表示模式的附加规则,放在正则模式的最尾部。
(1)g
默认只匹配一次,加g多次,主要用于搜索和替换

var regex = /b/;
var str = "abba";

regex.test(str); // true
regex.test(str); // true
regex.test(str); // true
上面代码中,正则模式不含g修饰符,每次都是从字符串头部开始匹配。所以,连续做了三次匹配,都返回true。

var regex = /b/g;
var str = "abba";

regex.test(str); // true
regex.test(str); // true
regex.test(str); // false
上面代码中,正则模式含有g修饰符,每次都是从上一次匹配成功处,开始向后匹配。因为字符串abba只有两个b,所以前两次匹配结果为true,第三次匹配结果为false

(2)i
忽略大小写

(3)m
m修饰符表示多行模式(multiline),会修改^和$的行为。默认情况下(即不加m修饰符时),^和$匹配字符串的开始处和结尾处,加上m修饰符以后,^和$还会匹配行首和行尾,即^和$会识别换行符(n)

/^b/m.test("anb") // true

上面代码要求匹配行首的b,如果不加m修饰符,就相当于b只能处在字符串的开始处。加上m修饰符以后,换行符n也会被认为是一行的开始

11.组匹配
(1)概述
正则表达式的括号表示分组匹配,括号中的模式可以用来匹配分组的内容

1.1/fred+/.test("fredd") // true
/(fred)+/.test("fredfred") // true
上面代码中,第一个模式没有括号,结果+只表示重复字母d,第二个模式有括号,结果+就表示匹配fred这个词

1.2var m = "abcabc".match(/(.)b(.)/);
m
// ["abc", "a", "c"]
上面代码中,正则表达式/(.)b(.)/一共使用两个括号,第一个括号捕获a,第二个括号捕获c。

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

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

1.4必须使用正则表达式的exec方法,配合循环,才能读到每一轮匹配的组捕获。

var str = "abcabc";
var reg = /(.)b(.)/g;
while (true) {
var result = reg.exec(str);
if (!result) break;
console.log(result);
}
// ["abc", "a", "c"]
// ["abc", "a", "c"]

1.4正则表达式内部,还可以用n引用括号匹配的内容,n是从1开始的自然数,表示对应顺序的括号。

/(.)b(.)1b2/.test("abcabc")
// true
上面的代码中,1表示第一个括号匹配的内容(即a),2表示第二个括号匹配的内容(即c)

1.5下面是另外一个例子。

/y(..)(.)21/.test("yabccab") // true
括号还可以嵌套。

/y((..)2)1/.test("yabababab") // true
上面代码中,1指向外层括号,2指向内层括号

1.6一个匹配网页标签的例子。

var tagName = /<(5+)>6*/;

tagName.exec("bold")[1]
// "b"
上面代码中,圆括号匹配尖括号之中的标签,而1就表示对应的闭合标签。

上面代码略加修改,就能捕获带有属性的标签。

var html = "Helloworld";
var tag = /<(w+)(5)>(.?)/g;

var match = tag.exec(html);

match[1] // "b"
match[2] // " class="hello""
match[3] // "Hello"

match = tag.exec(html);

match[1] // "i"
match[2] // ""
match[3] // "world"

(2)非捕获组

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

非捕获组的作用请考虑这样一个场景,假定需要匹配foo或者foofoo,正则表达式就应该写成/(foo){1, 2}/,但是这样会占用一个组匹配。这时,就可以使用非捕获组,将正则表达式改为/(?:foo){1, 2}/,它的作用与前一个正则是一样的,但是不会多带带输出括号内部的内容。

请看下面的例子。

var m = "abc".match(/(?:.)b(.)/);
m // ["abc", "c"]
上面代码中的模式,一共使用了两个括号。其中第一个括号是非捕获组,所以最后返回的结果中没有第一个括号,只有第二个括号匹配的内容。

下面是用来分解网址的正则表达式。

// 正常匹配
var url = /(http|ftp)://(7+)(/8*)?/;

url.exec("http://google.com/");
// ["http://google.com/", "http", "google.com", "/"]

// 非捕获组匹配
var url = /(?:http|ftp)://(9+)(/10*)?/;

url.exec("http://google.com/");
// ["http://google.com/", "google.com", "/"]
上面的代码中,前一个正则表达式是正常匹配,第一个括号返回网络协议;后一个正则表达式是非捕获匹配,返回结果中不包括网络协议。

(3)先行断言

x(?=y)称为先行断言(Positive look-ahead),x只有在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟着百分号的数字,可以写成/d+(?=%)/。

“先行断言”中,括号里的部分是不会返回的。

var m = "abc".match(/b(?=c)/);
m // ["b"]
上面的代码使用了先行断言,b在c前面所以被匹配,但是括号对应的c不会被返回。

(4)先行否定断言

x(?!y)称为先行否定断言(Negative look-ahead),x只有不在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟的不是百分号的数字,就要写成/d+(?!%)/。

/d+(?!.)/.exec("3.14")
// ["14"]
上面代码中,正则表达式指定,只有不在小数点前面的数字才会被匹配,因此返回的结果就是14。

“先行否定断言”中,括号里的部分是不会返回的。

var m = "abd".match(/b(?!c)/);
m // ["b"]
上面的代码使用了先行否定断言,b不在c前面所以被匹配,而且括号对应的d不会被返回。

  • xyz ↩

  • 0-9 ↩

  • A-Za-z0-9_ ↩

  • trnvf ↩

  • > ↩

  • < ↩

  • /rn ↩

  • rn ↩

  • /rn ↩

  • rn ↩

  • 文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/105988.html

    相关文章

    • 浅入正则(

      摘要:前一篇浅入正则一了解了实例化一个对象的原型方法的对象属性这些基础,大致知道正则怎么用,这一篇主要想了解一下正则怎么写。 with (javascript) 前一篇浅入正则(一)了解了实例化一个RegExp对象、RegExp的原型方法、RegExp的对象属性这些基础,大致知道正则怎么用,这一篇主要想了解一下正则怎么写。 元字符 元字符表随便就查得到,但这是会写正则最重要的基础,这里简单分...

      MRZYD 评论0 收藏0
    • JavaScript的正则表达式

      摘要:正则表达式是由普通字符例如字符到以及特殊字符称为元字符组成的文字模式。方法参数一个正则表达式对象。如果正则表达式没有标志,则会返回和相同的结果。其被视为一整个字符串,而不是一个正则表达式。 正则表达式 正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为元字符)。正则表达式使用单个字符串来描述、匹配一系列匹配某个...

      jsdt 评论0 收藏0
    • Date 对象

      摘要:构造函数参数无参数默认当天的日期一个用于表现日期的字符串分开传递的日月时间等值一个值更精确的是向构造器传递一些具体的数值年份月份从月月日期从到时数从到分钟从到秒钟从到毫秒数从到需要注意的是,如果所传递的值超过了被允许的范围,对象会自行启动溢 github Date() 构造函数 参数: 无参数(默认当天的日期) 一个用于表现日期的字符串 分开传递的日、月、时间等值 一个 timest...

      kgbook 评论0 收藏0
    • 细说 Javascript 类型篇() : typeof 操作符

      摘要:操作符还有可能是设计中最大缺陷,因为它几乎是完全破损的。由于用法与调用函数的语法相似,因此常被误以为是函数调用,实际上并不存在名为的函数,只是一个操作符而已。而列则表示对象内部的属性。属性文档中明确地给出了获得属性的途径,就是使用。 typeof 操作符(还有 instanceof)可能是 Javascript 设计中最大缺陷,因为它几乎是完全破损的。由于 typeof 用法与调用函数...

      PAMPANG 评论0 收藏0
    • RegExp对象

      摘要:方法用于从原字符串取出子字符串并返回,不改变原字符串。它的第一个参数表示子字符串的开始位置,第二个位置表示结束位置返回结果不含该位置方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。 正则表达式 正则表达式 Regular Expression 是一种表达文本模式的方法 类似字符串的模板 通常用来按照给定模式匹配文本 新建正则表达式有两种方式:字面量方式 以...

      wangdai 评论0 收藏0
    • JavaScript必会技能——正则表达式

      摘要:语法参数必填项,字符串或正则表达式,该参数指定的地方分割可选该参数指定返回的数组的最大长度,如果设置了该参数,返回的子字符串不会多于这个参数指定的数组。该数组通过在指定的边界处将字符串分割成子字符串。把正则表达式拆分成小表达式。 正则表达式是什么 RegExp 对象表示正则表达式,它是对字符串执行模式匹配的强大工具。 为什么使用正则表达式 测试字符串内的模式。例如,可以测试输入字符串...

      FrozenMap 评论0 收藏0

    发表评论

    0条评论

    最新活动
    阅读需要支付1元查看
    <