字符串中的正则和正则中的字符串

概要

正则主要应用在两个地方:

  • 字符串的方法可以使用正则的有:match()、matchAll、replace()、search()、split()
  • 正则的方法有:exec()、test()

match 和 exec

var str = "1a24a5qwerasadf";

var reg = /a/;

var result1 = str.match(reg);

var result2 = reg.exec(str);

console.log(result1);
console.log(result2);
// [ 'a', index: 8, input: '1245qwerasdf', groups: undefined ]
// [ 'a', index: 8, input: '1245qwerasdf', groups: undefined ]
//如果未正确匹配结果exec和match都会返回null

在正则不加g的情况下,两个方法匹配的结果是相同的。返回首次匹配成功的类数组对象。

var str = "1a24a5qwerasadf";

var reg = /a/g;//全局匹配

var result1 = str.match(reg);

var result2 = reg.exec(str);

console.log(result1);
console.log(result2);
// [ 'a', 'a', 'a', 'a' ]
// [ 'a', index: 1, input: '1a24a5qwerasadf', groups: undefined ]

gexec 没有效果,对 match 有效果,match 会返回所有匹配成功结果的数组。但是 exec 依然可以通过代码来达到 match 的效果。我们来研究下:

var str = "AaBbCcDd";

var reg = /[a-z]/g;

var result = reg.exec(str);
//[ 'a', index: 1, input: 'AaBbCcDd', groups: undefined ]
console.log(result);

var result = reg.exec(str);会返回类数组对象,但是 exec 的执行可以叠加。一直叠加到最后一个结果返回 null,在重新开始。结果就像下面的代码:

var str = "AaBbCcDd";

var reg = /[a-z]/g;

var result = reg.exec(str);//[ 'a', index: 1, input: 'AaBbCcDd', groups: undefined ]
var result = reg.exec(str);//[ 'b', index: 3, input: 'AaBbCcDd', groups: undefined ]
var result = reg.exec(str);//[ 'c', index: 5, input: 'AaBbCcDd', groups: undefined ]
var result = reg.exec(str);//[ 'd', index: 7, input: 'AaBbCcDd', groups: undefined ]
var result = reg.exec(str);//null
var result = reg.exec(str);//[ 'a', index: 1, input: 'AaBbCcDd', groups: undefined ]
var result = reg.exec(str);//[ 'b', index: 3, input: 'AaBbCcDd', groups: undefined ]
var result = reg.exec(str);//[ 'c', index: 5, input: 'AaBbCcDd', groups: undefined ]
var result = reg.exec(str);//[ 'd', index: 7, input: 'AaBbCcDd', groups: undefined 
var result = reg.exec(str);//null
// 无限循环
console.log(result);//null

这种写法太low了,我们使用 while 改写下:

var str = "AaBbCcDd";

var reg = /[a-z]/g;

var result = [];
while(reg.exec(str) !== null){//执行了一次exec
    result.push(reg.exec(str)[0]);//又执行了一次exec
};
console.log(result);
//[ 'b', 'd' ]

上面的结果返回的数组为什么少了两个元素。没错一个 while 循环我们执行了两次 exec。现在改写成执行一次的:

var str = "AaBbCcDd";

var reg = /[a-z]/g;

var result = [];
var res;

while((res = reg.exec(str)) !== null){//括号注意
    result.push(res[0]);
};
console.log(result);
//[ 'a', 'b', 'c', 'd' ]

match 中的分组捕获:

var phone = "110-110-999-213-222-987-987-776-010-345-456-198";

var reg = /(\d{3})\-\1/g;

var result = phone.match(reg);

console.log(result);
//[ '110-110', '987-987' ]

\1 代表与分组1(第一个括号)中一样的内容,\2代表与分组2(第二个括号)中一样的内容。常用于寻找相同子串,例如:

var str = "ABCCCCBBBWWWvdfWEEsfsEIIIOOOOOQJALSJJDCCNQQOIWJJDONDQDQ";

var reg = /(\w)\1+/g;

var result = str.match(reg);

console.log(result);
// [
//   'CCCC', 'BBB',
//   'WWW',  'EE',
//   'III',  'OOOOO',
//   'JJ',   'CC',
//   'QQ',   'JJ'
// ]

search

var str = "ABChioejfi23948178341QDQ";

var reg = /[a-z]/g;

var index = str.search(reg);

console.log(index);//3

返回第一个匹配成功字符串的下标,g 无任何作用。 search 还可以用 indexOf 来替代,比如上述结果可以更改为:

console.log(str.indexOf("i"));

search 就像用了正则的 indexOf 。例外 indexOf 和 search 没有成功匹配到结果会返回 -1 ,常用于字符串去重。

replace

  • 字符串形式的替换
var str = "爱情公寓中成果是一个00后,成果也是张伟的女朋友";

var reg = /成果/g;
const result = str.replace(reg,"诸葛大力");
console.log(result);
  • 函数形式的替换
var str = "爱情公寓中成果是一个00后,成果也是张伟的女朋友";

var reg = /成果/;
const result = str.replace(reg,function(a,b,c){
    // a:被替换的元素;b:索引; c:原字符串
    console.log(a)
    console.log(b)
    console.log(c)
    //return 的值就是要替换的值
    return "诸葛大力";
});
console.log(result);
// 成果
// 5
// 爱情公寓中成果是一个00后,成果也是张伟的女朋友
// 爱情公寓中诸葛大力是一个00后,成果也是张伟的女朋友

replace 中使用分组:

  • 字符串形式的分组捕获
    姓名交换是最简单的一个:
var str = "Tom David";

var reg = /(\w+)\s+(\w+)/g;
const result = str.replace(reg,"$2 $1");
console.log(result);
//David Tom

$1代表与分组1中一样的内容,$2代表与分组2中一样的内容。

  • 函数形式的分组捕获
    回调函数中可以接收分组捕获的内容,在 match 参数之后,$1 参数表示第一个捕获的内容,依次类推,不限制数量。
var str = "Tom David";

var reg = /(\w+)\s+(\w+)/g;
const result = str.replace(reg,function(match,$1,$2,index,str){
    console.log(match);
    console.log(index);
    console.log($1);
    console.log($2);
    console.log(str);
    return $2 + " " + $1;
});
console.log(result);
// Tom David
// 0
// Tom
// David
// Tom David
// David Tom

练习:

请把字符串 "爱情公寓中:★louyixiao★饰演胡一菲,★lijiahang★饰演张伟,★sunyizhou★饰演吕子乔,★lijinming★饰演陈美嘉,★chengguo★饰演诸葛大力。"转换成以下格式:
爱情公寓中:娄艺潇饰演胡一菲,李佳航饰演张伟,孙艺洲饰演吕子乔,李金铭饰演陈美嘉,成果饰演诸葛大力。

答案如下:

var nameObj = {
    louyixiao:"娄艺潇",
    lijiahang:"李佳航",
    sunyizhou:"孙艺洲",
    lijinming:"李金铭",
    chengguo:"成果"
};
var str = "爱情公寓中:★louyixiao★饰演胡一菲,★lijiahang★饰演张伟,★sunyizhou★饰演吕子乔,★lijinming★饰演陈美嘉,★chengguo★饰演诸葛大力。"

var reg = /★(\w+)★/g;
const result = str.replace(reg,function(match,$1,index,str){
    return nameObj[$1];
});
console.log(result);

是不是有点 mustache 语法的感觉。。。

split 字符串转数组

//根据空格切割字符串
var arr = '大力 羽墨    美嘉 吕嘉一 婉瑜'.split(/\s+/);
console.log(arr);//[ '大力', '羽墨', '美嘉', '吕嘉一', '婉瑜' ]

test

结果返回 true or false,常用于表单验证。

var str = "爱情公寓三新人诸葛大力赵海棠咖喱酱";

var reg = /大力/;

if(reg.test(str)){//true
    console.log(true);
}else{
    console.log(false);
}

写作日期 2020年2月23日 01点12分

推荐阅读更多精彩内容

  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    千机楼阅读 810评论 0 0
  • 注:参考《JavaScript语言精粹》第七章和第八章。 一、正则表达式的概念,作用 1.概念:正则表达式是一门简...
    yaya520阅读 148评论 0 1
  •   引用类型的值(对象)是引用类型的一个实例。   在 ECMAscript 中,引用类型是一种数据结构,用于将数...
    霜天晓阅读 309评论 0 1
  • 前言 对于正则,著称火星文字,见名知意主要它晦涩难懂,一直以来,看到它总是怕怕的,在平时,也只是简单的用用,其主要...
    itclanCoder阅读 148评论 0 3
  • 9.19--9.23 第7章 正则表达式 正则表达式是一个拆分字符串并查询相关信息的过程。 推荐练习网站: js ...
    如201608阅读 414评论 0 4