JavaScriptWeb前端之路让前端飞

例子详解正则表达式(二)

2017-04-11  本文已影响98人  issac_宝华
前言

接着例子详解正则表达式(一)往下讲。

1.特殊字符:. (小数点)

|字符|匹配规则|
|:--:|--|
|.|(小数点)匹配除换行符之外的任何单个字符。例如,/.n/将会匹配 "nay, an apple is on the tree" 中的 'an' 和 'on',但是不会匹配 'nay'。|

直接上例子:

var str="nay, an apple is on the tree";
// g标志表示全局搜索
var pattern = /.n/g;  // 匹配字符串中的一个2字节子串,由一个非换行符字符+n
console.log(str.replace(pattern, 'N'));  // nay, N apple is N the tree

传送门:demo


2.特殊字符:(x)

|字符|匹配规则|
|:--:|--|
|(x)|匹配 'x' 并且记住匹配项,就像下面的例子展示的那样。括号被称为 捕获括号。模式 /(foo) (bar) \1 \2/ 中的 '(foo)' 和 '(bar)' 匹配并记住字符串 "foo bar foo bar" 中前两个单词。模式中的 \1 和 \2 匹配字符串的后两个单词。注意 \1、\2、\n 是用在正则表达式的匹配环节。在正则表达式的替换环节,则要使用像 $1、$2、$n 这样的语法,例如,'bar foo'.replace( /(...) (...)/, '$2 $1' )。|

补充说明:正如上面的说的,() 可以记住第一次匹配到的字串,并依次将记住的字串放在一个列表里面,然后用 \x (x = 0,1,2,3……) 可以访问列表里面的子串,用在正则表达式里面,比如上面表格中的例子/(foo) (bar) \1 \2/中的(foo), 他第一次匹配到的子串一定是 "foo" (假定父字符串中有foo),那么foo就会被记录在一个列表,然后因为foo是第一个被匹配的,所以用\1可以访问到它,所以其实上面的正则表达式等价于/foo bar foo bar /,然后肯定会疑惑,为什么不直接这样写?看下面例子:

var str1 = "foo foo",
    str2 = "fooo fooooo", 
    str3 = "foo fo";
var pattern = /(fo*) \1/;
console.log(str1.replace(pattern, "FO*"));  // 输出FO*
console.log(str2.replace(pattern, "FO*"));  // FO*oo
console.log(str3.replace(pattern, "FO*"));  // foo fo

先看上面str1的输出,是FO*,你会发现 foo foo 全部被 FO* 替换。这不就相当于父串被 /fo* foo/匹配了吗?换言之 \1 等价于 foo,然后 fo*第一次匹配的正是 foo foo中的 foo
再看str2,输出的是 FO*oo,被替换掉的部分是:fooo fooo。那么上面代码中的pattern就相当于 /fo* fooo/
再看str3,是原样输出,为什么呢?patternfo* 第一次匹配到的字串是 foo,那么pattern就等价于 /fo* foo/,显然父串中并没有匹配项,因此原样输出。
小结:()特殊字符的正则表达式,会对父串匹配两次。第一次匹配是为了将每个记录放进”列表“中,然后解析当前正则表达式为"真"正则表达式(解析当前正则表达式中的\x x=123..n),第二次才开始真正的匹配。

传送门:demo


3.特殊字符:(?:x)

|字符|匹配规则|
|:--:|--|
|(?:x)|匹配 'x' 但是不记住匹配项。这种叫作非捕获括号,使得你能够定义为与正则表达式运算符一起使用的子表达式。来看示例表达式 /(?:foo){1,2}/。如果表达式是 /foo{1,2}/,{1,2}将只对 ‘foo’ 的最后一个字符 ’o‘ 生效。如果使用非捕获括号,则{1,2}会匹配整个 ‘foo’ 单词。|

补充说明:该字符和第二个特殊字符的作用有点类似,但是不同的是:该字符没有”记住“的能力。他存在意义正如表格中的介绍:

表达式是 /foo{1,2}/,{1,2}将只对 ‘foo’ 的最后一个字符 ’o‘ 生效。
ps:{1, 2}的意思是:至少前面的字符至少出现1~2次,比如?可以写成:{0, 1}

var str1 = str2 = "many foofoofoo";
var pattern1 = /(?:foo)+/,  // 匹配父串中的 foo...foo或foo
    pattern2 = /foo+/;  // 匹配父串中的foo...o或foo

console.log(str1.replace(pattern1, "FOO"));  // 输出many FOO
console.log(str2.replace(pattern2, "FOO"));  // 输出many FOOfoofoo

说道这里,我补充一点比较重要的知识点(不论你有没有明白到这一点):正则表达式在匹配父串的时候,是逐个字符去匹配,以每个字符作为一个单位

小结:(?:x) 是将 x 作为一个单位去匹配父串

传送门:demo


附录

字符 作用
g 全局搜索。
字符 匹配规则
{n,m} n 和 m 都是正整数。匹配前面的字符至少n次,最多m次。如果 n 或者 m 的值是0, 这个值被忽略。例如,/a{1, 3}/ 并不匹配“cndy”中得任意字符,匹配“candy”中得a,匹配“caandy”中得前两个a,也匹配“caaaaaaandy”中得前三个a。注意,当匹配”caaaaaaandy“时,匹配的值是“aaa”,即使原始的字符串中有更多的a。
上一篇下一篇

猜你喜欢

热点阅读