Javascript字符串检索的方法总结

字符串检索相关的操作总结

前言扩展: 正则

在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

你可能感兴趣的:(Javascript字符串检索的方法总结)