字符串检索相关的操作总结
前言扩展: 正则
在javascirpt里面可以用两种方法创建一个正则对象
1、使用字面量 /pattern/
var reg= /^[0-9]$/;
var reg= /ab+c/i;
2、使用构造函数 new (pattern[,flags])
第二个参数为可选, 包含属性 “g”、”i” 和 “m”,分别用于指定全局匹配、区分大小写的匹配和多行匹配
修饰符| 描述
—-|——|—-
i| 执行对大小写不敏感的匹配(ignore case)
g| 执行全局匹配(查找所有匹配项而非在找到第一个匹配后停止)(global)
m| 执行多行匹配。也就是,^ 和 $ 可以匹配字符串中每一行的开始和结束(行是由 \n 或 \r 分割的),而不只是整个输入字符串的最开始和最末尾处。(multiline)
注:正则的快速学习教程推荐
var reg= new RegExp('^abc{1}[0-9]*$','i'); 正则表达式运行时编译
var reg= new RegExp('^abc{1}[0-9]*$');
var reg= new RegExp(/ab+c/,'i'); 直接使用正则表达式构造对象
var reg= new RegExp(/ab+c/i)
注:ECMA6之前,如果第一个参数是正则表达式而不是字符串的时候,第二个参数必须省略,否则会跑出TypeError (“当从其他正则表达式进行构造时不支持标志”)异常
到了ECMA6,不再抛出错误。那此时第二个参数有没有用呢?我们来试一试
var reg= new RegExp(/^abc{1}[0-9]*$/,'i'); reg.test('Abc5');
//true 实际等同下一条
var reg= new RegExp(/^abc{1}[0-9]*$/i); reg.test('Abc5');
//true
var reg= new RegExp(/^abc{1}[0-9]*$/); reg.test('Abc5');
//false
可以看到,当第一参数是正则表达式的时候,第二个参数还是可以正确使用的
(chrome v49.0.2623)
方法| 描述
—-|——|—-
compile| 编译正则表达式
exec| 检索字符串中指定的值。返回找到的值,并确定其位置。
test| 检索字符串中指定的值。返回 true 或 false。
注:正则的快速学习教程推荐http://deerchao.net/tutorials/regex/regex-1.htm
下面正式进入主题
1、test
RegExpObject.test(string)
test() 方法是正则对象的一个方法,用于检测一个字符串是否匹配某个模式,返回 true 或 false。
对,我们可以编写相应的正则方法,然后使用Reg对象的test方法来检测是否存在相关字符串,而且还可以很自由地掌控检测规则,例如目标字符串在多少位后出现,重复出现几次等等
实际上与这个表达式是等价的 (r.exec(s)!=null)
var reg= new RegExp(/^abc{1}[0-9]*$/); reg.test('abc5'); //true
var reg= new RegExp(/^abc{1}[0-9]*$/); reg.test('cccabc5'); // false
var reg= new RegExp(/^abc{1}[0-9]*$/i); reg.test('Abc5'); //true
var reg= new RegExp(/^abc{1}[0-9]*$/); reg.test('Abc5'); //false
//在开头abc出现一次之后跟着若干个数字
test方法会更新lastIndex属性
var strs='Markdown markdown markdown';
var reg=new RegExp(/markdown/g);
reg.test(strs);//true
console.log(reg.lastIndex)//17
reg.test(strs);//true
console.log(reg.lastIndex)//26
reg.test(strs);//false
console.log(reg.lastIndex)//0
2、exec
RegExpObject.exec(string)
在循环中反复地调用 exec() 方法是唯一一种获得全局模式的完整模式匹配信息的方法。
exec也是正则对象的一个方法,可检索字符串中指定的值,返回一个数组,其中存放匹配的结果。它的使用比test()或者支持正则的StringObject的方法更复杂
如果未找到匹配,则返回值为 null
如果不包括g标志,返回一个结果数组,此数组的第 0 个元素是与正则表达式相匹配的文本,第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本(如果有的话),第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本(如果有的话),即返回stringObject.match()相同的结果;
除了数组元素和 length 属性之外,exec() 方法还返回两个属性。index 表示匹配结果在原字符串中的索引。input 属性则存放的是被检索的字符串 string。
如果正则表达式包括g标志,返回一个数组,数组的内容是所有包含匹配的字符串。不是位置!不是位置!;它会在RegExp的lastIndex置顶的位置开始检索字符串,当exec()找到了一个与表达式匹配的文本后,在匹配后,会吧lastIndex改为匹配文本的最后一个字符的最后一个位置。That mean 我们可以通过反复调用exec()来便利字符串中的所有匹配文本,当exec()再找不到匹配的文本时,将返回null,并把lastIndex置为0;
注意:它不会一次返回所有匹配的项,而是每次执行都从lastIndex开始找一个匹配项,就返回
var str="Jianshu markdown bu zhi chi table Markdown,markdown repeat";
var agi=new RegExp('markdown','gi');
//var agi=new RegExp(/markdown/gi);
console.log(agi.exec(str)) console.log(ag.lastIndex)
console.log(agi.exec(str)) console.log(ag.lastIndex)
console.log(agi.exec(str)) console.log(ag.lastIndex)
//["markdown", index: 8, input: "Jianshu markdown bu zhi chi table Markdown , markdown repeat"]
//16
//["Markdown", index: 34, input: "Jianshu markdown bu zhi chi table Markdown , markdown repeat"]
//42
//["markdown", index: 45, input: "Jianshu markdown bu zhi chi table Markdown , markdown repeat"]
//53
//null
//0
//global模式下每次返回一个匹配的值,改变lastIndex的值
var ai=new RegExp('markdown','i');
//var ai=new RegExp(/markdown/i);
console.log(ai.exec(str));console.log(ai.lastIndex)
console.log(ai.exec(str));console.log(ai.lastIndex)
console.log(ai.exec(str));
//["markdown", index: 8, input: "Jianshu markdown bu zhi chi table Markdown , markdown repeat"]
//0
//["markdown", index: 8, input: "Jianshu markdown bu zhi chi table Markdown , markdown repeat"]
//0
//["markdown", index: 8, input: "Jianshu markdown bu zhi chi table Markdown , markdown repeat"]
//没有global标志,三次执行结果一样,不会改变lastIndex的值
3、search
stringObject.search(regexp)
用于检索字符串中指定的子字符串,或检索 与正则表达式相匹配的子字符串。返回第一个与regexp相匹配的子串的起始位置,如果要执行忽略大小写的检索,追加标志i
特性:对大小写敏感,且不执行全局匹配,忽略标志g,也忽略lastIndex属性,总是从字符串的开始进行检索
var a="Jianshu markdown bu zhi chi table Markdown";
a.search('jianshu'); //-1
a.search('Jianshu'); //0
a.search('markdown'); //8
a.search(/\bmarkdown\b/) ; //8
a.search(/JIanShu/i) //0 使用search做忽略大小写的匹配呢,就是在后面加i
4、match
stringObject.match(regexp)
当字符串匹配到正则表达式的时候,match()会提取匹配项
- 如果正则表达式包括g标志,返回一个数组,数组的内容是所有包含匹配的字符串。注意!不是位置!不是位置!;
- 如果不包括g标志,返回一个数组,内容是第一个匹配的字符串,即返回与Reg.exec(str)相同的结果;
而且返回的数组拥有额外的一个input属性,该属性包含原始字符串,另外还有一个index属性,表示匹配结果在原字符串中的索引 - 如果未找到匹配,则返回值为 null
参数是一个正则表达式对象,如果传入一个非正则表达式对象,会隐式使用New RegExp(obj)将其转换为正则表达式对象
var b='Markdown markdown markdown';
b.match(/markdown/ig) //["Markdown", "markdown", "markdown"]
b.match(/markdown/i) //["Markdown"]
b.match('markdown') //["markdown"] 这里发生了一次隐式转换
b.match('markdown/i') //null 因为是直接吧markdown/i整个字符串进行RegExp构建的
var c=b.match(/markdown/)
console.log(c); //["markdown", index: 9, input: "Markdown markdown markdown"]
//尝试设置lastIndex改变匹配起始处
var b='Markdown markdown markdown';
var temp=new RegExp(/markdown/);
temp.lastIndex=18;
var c=b.match(temp);
console.log(c)
//["markdown", index: 9, input: "Markdown markdown markdown"]
//似乎没有用
在w3c的页面找到了一个说明
重要事项:不具有标志 g 和不表示全局模式的 RegExp 对象不能使用 lastIndex 属性。
好,那在全局模式再试一下
var b='Markdown markdown markdown';
var temp=new RegExp(/markdown/g);
temp.lastIndex=18;
var c=b.match(temp);
console.log(c)
//["markdown", "markdown"]
//依然没有用
5、includes
includes() 方法用于 判断一个字符串是否被包含在另一个字符串中,如果是返回 true,否则返回 false。该方法区分大小写
兼容性:ECMA6,chrome 41+、firefox 40+,safari 9+;ie全系不支持
stringObject.includes(searchString [, position])
searchString 将要搜寻的子字符串。 position
可选。从当前字符串的哪个索引位置开始搜寻子字符串;默认为0。
var str = 'To be, or not to be, that is the question.';
console.log(str.includes('To be')); // true
console.log(str.includes('question')); // true
console.log(str.includes('nonexistent')); // false
console.log(str.includes('To be', 1)); // false
console.log(str.includes('TO BE')); // false
Polyfill:
if (!String.prototype.includes) {
String.prototype.includes = function(search, start) {
'use strict';
if (typeof start !== 'number') {
start = 0;
}
if (start + search.length > this.length) {
return false;
} else {
return this.indexOf(search, start) !== -1;
}
};
}
总结一下
str.includes()跟RegExp.test()类似,返回一个布尔值
str.match()跟RegExp.exec()类似,返回一个数组或null
str.search()返回第一次出现的位置,与indexOf类似
会更新lastIndex属性的有RegExp.test()以及RegExp.exec()
参考资料:
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/includes
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp
http://www.w3school.com.cn/jsref/jsref_obj_regexp.asp