- + 匹配一次或更多次的重复
+?匹配一次或更多次的重复,但是在能使整个匹配成功的前提下使用最少的重复
贪婪匹配:尽可能多的匹配,而且允许后续正则表达式继续匹配。+和*就是贪婪匹配。
非贪婪匹配:只需要在待匹配的字符后边跟一个?就行。如+?、*?、??、{1,5}?
-
字符串中常用的关于正则表达式的方法(4个):
- search() 参数是正则表达式。如果参数不是正则表达式,那么会调用RegExp的构造函数将其转化为正则表达式。该函数返回第一个匹配项的索引,如果匹配不成功,则返回-1;该方法不支持全局检索,会忽略掉修饰符g
- replace(arg1,arg2) arg1是字符串或者正则表达式,arg2是一个字符串或者函数。arg2是函数的时候,如果只有一个匹配项,那么传递给函数3个参数:匹配项、匹配项在字符串中的位置、原字符串。如果正则表达式定义了多个捕获组,传递给函数的参数依次是模式的匹配项、第一个捕获组的匹配项、第二个组的匹配项……最后两个参数依然是模式的匹配项在字符串中的位置和原始字符串。如果在替换文本中出现了$加数字,那么replace函数会用文本替换这两个字符。这个函数应该返回一个字符串用来代替匹配项。默认情况下会返回undifined。
- split()方法基于指定的分隔符将字符串进行分割,并将结果放到数组中。分隔符可以是字符串也可以是RegExp对象。分隔符为第一个参数,第二个参数是可选的,代表着数组的大小。
- match()方法只有一个参数,就是正则表达式,返回的是匹配结果的数组。数组中第一项是完整的匹配,接下来存放的是第一个捕获组的匹配项、第二个组的匹配项……。如果给match函数传入的参数是一个非全局的正则表达式,那么返回的数组有两个属性:input和index,这个和正则表达式的exec()函数返回的结果一样。
-
RegExp对象的方法(两个):
- exec()方法的参数是字符串。找到匹配项之后返回的是数组,没有找到的话返回的是null。数组中的第一项是正则表达式的匹配项,接下来的是圆括号中的子表达式匹配项。数组包含两个属性index和input。Index表示的是匹配项在字符串中的位置,input表示的是应用正则表达式的字符串。对于该方法,即使在正则表达式中有修饰符g,仍然只会返回一个匹配项,这点与字符串的match方法不同。在不设置全局修饰符的情况下,在同一个字符串上调用该方法,返回的永远是第一个匹配项。如果设置了全局修饰符,每次调用都会在字符串中继续检索新的匹配项。然后会把RegExp对象的lastindex属性设置为字符串下一次开始检索的位置。如果没有发现匹配项,则把lastindex属性设置为0。
- test()方法参数是字符串,如果包含正则表达式的匹配结果,就返回true。test()方法也会修改lastindex属性,就像exec()方法一样。
- RegExp对象的属性:
- source属性是只读的字符串,包含正则表达式的文本,
- global属性表示是否带有修饰符g
- ignoreCase属性表示是否带有修饰符i
- Multiline属性表示是否带有修饰符m
- Lastindex字符串中下一次检索开始的位置
- 用\b来表示退格符,退格符即backspace键对应的字符,它显示的时候是将光标退回到前一个字符,但不会删除光标位置的字符。如果后边有新的字符,将覆盖退回的那个字符,这与我们在文本编辑器中按backspace的效果不一样。
\t是制表符,按键盘上的Tab键就是,它是一个字符,但显示的时候通常会是按8个字符宽度跳到下一个制表位置
- 括号的作用:
首先明白管道符(|)的作用是分隔用于选择的字符。如:/ab|cd|ef/可以匹配字符串'ab'、'cd'、'ef'
- 作为分组使用,即把单独的项目合成子表达式。如:/(ab)+/把ab作为一个整体去匹配。这个子表达式可以使用*、+、|、*、?
- 在完整的模式中定义子模式,捕获数据。如:
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2017-06-12";
console.log( string.match(regex) );
// => ["2017-06-12", "2017", "06", "12", index: 0, input: "2017-06-12"]
捕获的数据可以被提取出来。如果有多个捕获组,就使用$1、$2等来提取数据。
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2017-06-12";
regex.test(string); // 正则操作即可,例如
//regex.exec(string);
//string.match(regex);
console.log(RegExp.$1); // "2017"
console.log(RegExp.$2); // "06"
console.log(RegExp.$3); // "12"
这里是使用构造函数的全局属性($1)来进行提取的。
- 创建引用,引用的是与字模式相匹配的文本,不是子模式。只需要在\后面加上数字就可以。这个数字指定的是子表达式在正则表达式中的位置,这个位置是根据参与计数的左括号的位置来计算的。即在同一正则表达式的后边引用前面的子表达式,也被称为反向引用。
如:/["'][^"']\1/匹配的是""或者’,而/[""'][^""']["']/有可能匹配出"'(单引号和双引号)这种情况。另外注意正则表达式不允许用双引号括起来的内容中有单引号,反之亦然。
而且不能再字符类(将直接量放进[]中就是字符类)中使用反向引用。
当有括号嵌套的时候:只需要按照参与计数的左括号来区分分组情况,就可以明白每个分组代表着什么。如:
var regex = /^((\d)(\d(\d)))\1\2\3\4$/;
var string = "1231231233";
console.log( regex.test(string) ); // true
console.log( RegExp.$1 ); // 123
console.log( RegExp.$2 ); // 1
console.log( RegExp.$3 ); // 23
console.log( RegExp.$4 ); // 3
引用不存在的分组:
因为反向引用,是引用前面的分组,但我们在正则里引用了不存在的分组时,此时正则不会报错,只是匹配
反向引用的字符本身。例如 \2,就匹配"\2"。注意 "\2" 表示对 "2"进行了转义。 即\2==2会显示false。
分组后面出现量词:
分组后面有量词的话,分组最终捕获到的数据是最后一次的匹配 。如:
var regex = /(\d)+/;
var string = "12345";
console.log( string.match(regex) );
// => ["12345", "5", index: 0, input: "12345"]
以及
var regex = /(\d)+ \1/;
console.log( regex.test("12345 1") );
// => false
console.log( regex.test("12345 5") );
// => true
- 非不捕获括号。之前说的括号,都会捕获它们匹配到的数据,以便后续引用 。如果只想要括号最原始的功能,但不会引用它,即,既不在 API里引用,也不在正则里反向引用 ,那就需要使用非捕获括号(?:)如:
var regex = /(?:ab)+/g;
var string = "ababa abbb ababab";
console.log( string.match(regex) );
// => ["abab", "ab", "ababab"]
只会匹配ab,不会获取它和引用它。
- 匹配位置的时候可以用来进行插入操作。
指定位置的匹配。有一些正则表达式匹配的是字符之间的位置,而不是实际的字符。例如:\b匹配的是一个单词的边界,即位于\w(ASCII单词)字符和\W(非ASCII单词字符)之间的边界,或位于一个ASCII单词与字符串开始或结尾之间之间的边界,但是\b在字符类中表示的是退格符。\B则是把匹配的锚点定位在不是单词的边界之外。如:/[Bb]script/与javaScript和postscript匹配,但是不与script匹配。像\b这样指定匹配发生的合法位置的元素被称为正则表达式的锚。常用的锚还有^、$
- 先行断言和负向先行断言:
先行断言:(?=p)就是p前边的位置。如:
var result = "hello".replace(/(?=l)/g, '#');
console.log(result);
// => "he#l#lo
负向先行断言:(?!p)就是后面跟的不是p的位置。如:
var result = "hello".replace(/(?!l)/g, '#');
console.log(result);
// => "#h#ell#o#"
- 正则表达式中的修饰符m代表多行匹配模式,这个时候如果被检索的字符串包括多行,那么^$除了匹配字符串的开头和结尾,还能匹配每行的开头和结尾。