重要问题

“+”导致匹配不上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
<head></head>

<body>
<div>ABS+PC,抗跌落和震动</div>
</body>
<script src="http://www.lazycat.cc/Doctor/Application/Doctor/View/css/bower_components/jquery/dist/jquery.min.js"></script>
<script>
function replaceAll(obj ,oldStr, newStr)
{
return obj.replace(new RegExp(">[\\s]*"+oldStr+"[\\s]*<","gm"),function(word){
return ">"+newStr+"<"}
);
}

var body=$("body").html();
body=replaceAll(body,"ABS+PC,抗跌落和震动","ssssss");
$("body").html(body);
</script>
</html>

像这样有个加号,文本不会被替换,但是删除两个加号后就能正常被替换了

解决办法是进行转义

1
2
3
4
+号在正则表达式中是有意义的,要转义
oldStr = oldStr.replace('+','\\+');
return obj.replace(new RegExp(">[\\s]*"+oldStr+"[\\s]*<","gm"),function(word){
return ">"+newStr+"<"}
  • +需要转义,它表示多个字符,+才是字面的加号。
  • +在正则里有自己的含义,若要当普通字符使用,需要写成“+”

replace()函数使用

语法:
string.replace(regexp, replacement)
参数:
regexp:必需。要搜索的值或正则表达式。
replacement:必需。指定替换文本或生成替换文本的函数。
返回值:已替换指定值的新字符串。
w3school:JavaScript String replace() 方法

一、常规使用

  • 将aaa替换为111:
    1
    2
    var str = "aaa,bbb,ccc";
    str.replace('aaa', "111");//输出'111,bbb,ccc'
  • 将连续的字母替换为111:
    1
    2
    var str = "aaaaaaa,bbbbbb,ccc";
    str.replace(/\w+/g, "111");//输出'111,111,111'
  • 将所有字母全部替换为1:
    1
    2
    var str = "aaa,bbb,ccc";
    str.replace(/\w/g, "1");//输出'111,111,111'

二、$1、$2、…、$99等使用

1
2
var str = "aaa,bbb,ccc";
str.replace(/(\w+),(\w+),(\w+)/, "$3,$2,$1");//输出'ccc,bbb,aaa'
  • $1代表第一个(\w+)匹配到的内容,即aaa
  • $2代表第一个(\w+)匹配到的内容,即bbb
  • $3代表第一个(\w+)匹配到的内容,即ccc
1
2
var str = "aaa、bbb、ccc";
str.replace(/(\w)+、(\w)+、(\w)+/, "$3$2$1");//输出'cba'
  • $1代表第一个(\w)匹配到的内容,即a
  • $2代表第一个(\w)匹配到的内容,即b
  • $3代表第一个(\w)匹配到的内容,即c

结论:$1、$2、…、$99 表示正则表达式中的括号匹配项的结果。

三、函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//输出'hello,world'
var str = "Hello,World";
str.replace(/[A-Z]/g, function(val){
return val.toLowerCase()
});

//输出'HELLO,WORLD'
var str = "Hello,World";
str.replace(/[a-z]/g, function(val){
return val.toUpperCase()
});

//输出'000,000,111'
var str = "aaaaaaa,bbbbbb,ccc";
str.replace(/\w+/g, function(val){
return val === 'ccc' ? '111':'000'
});

**一个经典的例子——模板字符匹配: **

1
2
3
4
5
6
7
8
9
10
var data = {
title:'标题',
subTitle: '副标题',
content:'内容'
}
var str='这是一段内容,标题是{{title}},副标题是{{subTitle}},内容是{{content}}'

str.replace(/\{\{(.*?)\}\}/g, function(val,key){
return data[key]
});

输出:这是一段内容,标题是标题,副标题是副标题,内容是内容

这里函数的第一个参数是匹配的内容,第二个参数是括号匹配的结果

四、其他常用正则表达式

邮箱格式:^[a-z0-9A-Z]+[- | a-z0-9A-Z . _]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-z]{2,}$

正整数:^1-9*$

  • 身份证号
    ^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$
  • ip地址
    ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$
  • 数字或英文字母
    ^([0-9a-zA-Z]+)$
  • 手机号码
    ^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\d{8}$
  • 日期时间格式YYYY-MM-DD HH:mm:ss
    ^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})$
  • 日期格式YYYY-MM-DD
    ^(\d{4}-\d{2}-\d{2})$
  • 合法url
    (https?|ftp|file)://[-A-Za-z0-9+&@#/%?=_|!:,.;]+[-A-Za-z0-9+&@#/%=_|]
  • 最多三位小数
    ^(?:[1-9]\d*|0)(?:\.\d{1,3})?$
  • 大于等于0且最多三位小数
    ^(?!0+(?:\.0+)?$)(?:[1-9]\d*|0)(?:\.\d{1,3})?$
  • 最多两位小数
    ^(?:[1-9]\d*|0)(?:\.\d{1,2})?$
  • 大于等于0且最多两位小数
    ^(?!0+(?:\.0+)?$)(?:[1-9]\d*|0)(?:\.\d{1,2})?$
  • 至少两个字符,中文或英文
    ^([a-zA-Z\u4E00-\u9FA5]+)$
  • 3-15个字符,仅限数字、字母、斜杠、横杠、点
    ^[-/0-9A-Za-z.]{3,15}$

replace()函数详细说明

1. 方法简介

该方法的签名是:replace([RegExp|String],[String|Function])。

该方法 返回一个新的字符串,但并不改变字符串本身。

该方法接收2个参数,
第一个参数可以是字符串,也可以是一个正则表达式;
第二个参数可以是一个字符串,也可以是一个函数。

2. replace()使用

2.1 replace(字符串,字符串)
假如我们有一个字符串中出现了错别字”背景“,需要用”北京“来替换,那么我们可以如下搞定:

1
2
3
let str = '我爱背景天安门';
str = str.replace('背景','北京');
console.log(str); // 输出结果:我爱北京天安门

但这个用法有一个问题:

1
2
3
4
let str = '我爱背景天安门,但是背景雾霾太严重';
str = str.replace('背景','北京');
// 输出结果:我爱北京天安门,但是背景雾霾太严重
console.log(str);

我们发现,如果字符串str中有多个待替换的子串,比如本例中的“背景”,出现了2次,那么replace()方法只能给我们用目标字符串(北京)替换掉第1次出现的”背景”。
如果想把所有的”背景”都给替换了,就必须调用多次。

此使用方法bug: 只能替换一次 多次替换需要多次调用

2.2 replace(正则表达式,字符串)

1
2
3
4
let str = '我爱背景天安门,但是背景雾霾太严重';
str = str.replace(/背景/g,'北京');
// 输出结果:我爱北京天安门,但是北京雾霾太严重
console.log(str);

这里需要说明的是,str.replace(/背景/g,“北京”)的第一个参数 ”/背景/g“ 是一个正则表达式,使用/ /的正则写法是JavaScript中正则表达式的字面量写法。
在此处,正则表达式的末尾有个g,它表示match源字符串str中所有匹配项。
这里如果没有g,那么也只能匹配到第一个错别字”背景“,只有加了这个g,才能匹配到所有的”背景“。

2.3 replace(正则表达式,function(){})
以上的用法还是比较直观的,但是能实现的功能也比较简单,如果需要做一些复杂的字符串替换运算,那么就需要使用较为高级(复杂)的用法,就是 正则+function 的用法。说白了就是第一参数传一个正则表达式,我们下面称之为RegArg;第二个参数给一个函数,我们下面称之为FuncArg。这也是replace()的核心用法。

本质 :对str使用RegArg做match()匹配,如果匹配到多项结果(比如使用了全局匹配g,或者分组),那么每一个匹配结果都将执行一次FuncArg函数,并且用该函数的返回值替代源字符串中的匹配项。

2.3.1 简单用法,正则表达式不使用分组

1
2
3
4
5
6
7
let str = '我爱背景天安门,但是背景雾霾太严重';
str = str.replace(/背景/,function(){
console.log(arguments);
return '北京'
});

console.log(str);

解析:

  • 本例的目的是:把原字符串中的’背景’,替换为’北京’。
  • 正则表达式没有使用全局匹配符g,所以只替换了源字符串中第一个‘背景’子串,FuncArg只执行了一次。

replace()函数第一个参数是简单正则表达式,第二个参数是函数时:
这个函数是有参数的,而且这些参数是默认的。

  • arguments[0]是匹配到的子字符串
  • arguments[1]是匹配到的子串的索引位置
  • arguments[2]是源字符串本身

本例如果想替换所有的‘背景’为‘北京’,只需要让正则表达式后加个g。

1
2
3
4
5
6
7
let str = '我爱背景天安门,但是背景雾霾太严重';
str = str.replace(/背景/g,function(){
console.log(arguments);
return '北京'
});

console.log(str);

我们可以看到,输出了2个Arguments,因为我们使用全局匹配g后,会match到2个项,所以就执行了2次function。
第一个跟前边一样,第二个arugments的索引位置是10,因为源字符串中第二个‘背景’的索引是10.

eg:把捐款是100元以下的金额数用‘**’来替换掉。

1
2
3
4
5
6
7
var txt ='刘菲:50元。张常成:150元。孙玉杰:200元。李明轩:20元。李子豪:1500元。';
txt = txt.replace(/\d+/g,function(){
console.log(arguments);
return arguments[0].length > 2 ? arguments[0] : '**';
});

console.log(txt);

2.3.2 复杂用法,正则表达式使用分组
eg:这个例子的意图是:把所有以“万”为单位的捐款,其金额改为‘元’。比如 :4万,改为40000元

1
2
3
4
5
6
7
var txt ='刘菲:5万。张常成:5000元。孙玉杰:2000元。李明轩:20万。李子豪:8500元。';
txt = txt.replace(/(\d+)(万)/g,function(){
console.log(arguments);
return arguments[1] + '0000' + '元';
});

console.log(txt);

输出结果是:

replace()函数第一个参数是分组正则表达式,第二个参数是函数时:

  • arguments[0]是匹配到的子字符串
  • arguments[1]是匹配到的第1个分组项
  • arguments[2]是匹配到的第2个分组项
  • arguments[3]是匹配到的字符串的索引位置
  • arguments[4]是源字符串本身

正则匹配RegExp

JS高级 之 RegExp - 正则表达式
JS 正则表达式(正则匹配RegExp)


相关链接

  1. 关于js正则匹配的问题,怎么加上一个”+”就匹配不上了
  2. js正则表达式replace中参数为$1、$2、…、$99、函数等用法以及常用的正则表达式
  3. 【JavaScript】详解JavaScript中的replace()函数
  4. JavaScript replace() 方法

=================我是分割线=================

欢迎到公众号来唠嗑: