lznbuild / my-blog

自己的博客
9 stars 1 forks source link

JavaScript正则表达式 #1

Open lznbuild opened 4 years ago

lznbuild commented 4 years ago

创建正则的两种方式

1.创建RegExp对象

// JavaScript中有一个特殊对象,RegExp对象
var reg = new RegExp('a'); 
'12a3'.replace(reg, '&');  // '12&3'

2.创建正则表达式字面量

var reg = /a/;
'12a3'.replace(reg, '&'); // '12&3'

两种创建方式的区别有两点:

1.创建RegExp对象的方法,可以创建动态正则

var str = '2';
var reg = /str/;   // 这里的str只是单纯的字符串'str'
reg.test('123'); // false
reg.test('11str22'); // true

var newReg = new RegExp(str);  // 这里的str是一个变量,也就是字符串2
reg.test('123'); //true
reg.test('11str22') // false

2.创建RegExp对象的方法,需要对特殊字符做转义处理

var reg = new RegExp('\\d'); // \d是正则中的元字符,下面会有详细介绍,表示匹配数字,在这之前要加转义处理
reg.test('jk'); // false
reg.test('12'); // true

var strReg = /\d/; // 直接用\d
strReg.test('1'); // true

search() 和indexOf方法的返回跟判断完全一致,可以写正则,indexOf不可以

字符串对象共有4个方法,可以使用正则表达式:match()、replace()、search()和split(),test()

正则其实只匹配字符和位置,这句话就概括了正则的精髓。

修饰符

g 表示全局匹配

'1232'.replace(/2/, '$'); // '1$32',只匹配第一个,后面即使有字符匹配正则的规则,也不会再替换

'1232'.replace(/2/g, '$'); // '1$3$',所有和正则匹配规则的字符都会被替换

i 表示不区分大小写

'abcABC'.replace(/A/g, '$'); // 'abc$BC'
'abcABC'.replace(/A/ig, '$'); // '$bc$BC'

m 表示多行匹配

// m修饰符的使用,多行匹配
var result = "I\nlove\njavascript".replace(/^|$/gm, '#'); // 每一行都匹配一下此正则
console.log(result); 
// #I#
// #love#
// #javascript#

这里只列举常用的,更多请查询MDN

特殊字符

普通的特殊字符

字符 描述
^ 匹配字符串的开头
$ 匹配字符串的结尾
. 匹配几乎任意字符。换行符、回车符、行分隔符和段分隔符除外
\d 匹配数字
\D 匹配非数字
\b 匹配字符边界
\B 匹配非字符边界
\s 匹配空白字符, \t,\v,\n,\r,\f都是空白符
\S 匹配非空白字符
\w 匹配字母数字或下划线
\W 匹配非字母数字或下划线

有些不好理解,所以配合案例

'moon'.replace(/\bm/, '&'); // '&oon',因为m字符前面的位置,符合匹配规则\w 与 ^ 之间的位置。

"[JS] Lesson_01.mp4".replace(/\b/g, '#'); // "[#JS#] #Lesson_01#.#mp4#",这个案例很能说明\b的匹配规则了

而\B呢,当然就和\b相反了,具体就是\w 与 \w、 \W 与 \W、^ 与 \W,\W 与 $ 之间的位置。

"[JS] Lesson_01.mp4".replace(/\B/g, '#'); // => "#[J#S]# L#e#s#s#o#n#_#0#1.m#p#4

\10 分组 展示为\1 和0的写法 \1(?:0)

// $1,$2是在正则以外的写法,必须调用跟正则有关的方法后才能使用
var re = /(\w+)\s(\w+)/;
console.log(re.$1)//报错
var str = "John Smith";
var newstr = str.replace(re, "$2, $1"); // 调用replace方法用到了re正则,可以使用$1,$2
console.log(newstr);    // Smith, John

方法调用后的特殊字符

// $& 匹配到的子串文本
// $` 匹配到的子串的左边文本
// $' 匹配到的子串的右边文本,包含匹配项
// $$ 美元符号
var result = "2+3=5".replace(/=/, "$&$`$&$'$&");
console.log(result);
// => "2+3=2+3=5=5"
// 匹配字符s,前面紧跟j字符的s,只匹配s
'jsis'.replace(/(?<=j)s/,'@'); // j@is

这里只列举常用的,更多请查询MDN

匹配位置的总结

    ^ & \b \B (?=p)  (?!p)

描述数量的特殊字符

描述数量的特殊字符前面必须跟有效的字符(没字符的话描述谁的数量呢)

字符 描述
+ 表示字符出现一次或多次,等价于{1,}
* 表示字符出现0次或多次,等价于{0,}
? 表示字符出现0次或1次,等价于{0,1}
{n} 表示字符出现2次
{2,5} 表示字符出现2-5次
{2,} 表示字符出现2次或多次(大于2)
 // 这里只放一个案例,其他数量字符使用同理
 '142344546'.replace(/4{2}/, '$'); // 1423$546

?不光表示数量特殊字符,还可以表示惰性匹配,跟在数量特殊字符的后面。

 // /\d{2,5}?/ 表示,虽然 2 到 5 次都行,当 2 个就够的时候,就不再往下尝试了。
var regex = /\d{2,5}?/g;
var string = "123 1234 12345 123456";
console.log( string.match(regex) ); // => ["12", "12", "34", "12", "34", "12", "34", "56"]

// 实际案例,想匹配id="xxxxx"这段字符
var regex = /id=".*"/ 
var string = '<div id="container" class="main">'; 
console.log(string.match(regex)[0]); // => id="container" class="main"
/id=".*?"/               //id="container" 涉及到回溯,最好的写法是 /id="[^"]*"/

常用方法(只列举常用的)

字符串对象共有4个方法,可以使用正则表达式:match()、replace()、search()和split()。

// replace以上实例用作多次,不再赘述。

// match  返回所有匹配字符组成的数组,不加修饰符g,返回类数组
'2m9jklj7jkl'.match(/\d/g) // ["2", "8", "9", "7"]  

// search() 返回第一个匹配项的下标,即使加修饰符g,也只匹配第一个下标,search方法就是这样定义的
'sdf7jkl87df0'.search(/\d/) // 3

// split 按匹配项进行字符串分割,返回分割后的所有项组成的数组  
'1jk23'.split(/\d/) // ["", "jk", "", ""]

test()方法用于正则表达式,有匹配项就返回true

// 以上实例用作多次,不再赘述。

关于正则使用的案例

数字的千位分隔符表示法(比如把 "12345678",变成 "12,345,678")

var regex = /(?!^)(?=(\d{3})+$)/g;
var result = "12345678".replace(regex, ',')
console.log(result); // => "12,345,678"

result = "123456789".replace(regex, ',');
console.log(result);
// => "123,456,789"

匹配标签

var regex = /<([^>]+)>[\d\D]*<\/\1>/;
var string1 = "<title>regular expression</title>";
var string2 = "<p>laoyao bye bye</p>";
var string3 = "<title>wrong!</p>";
console.log( regex.test(string1) ); // true
console.log( regex.test(string2) ); // true
console.log( regex.test(string3) ); // false

实体字符转换为等值的HTML。

function unescapeHTML (str) {    
    var htmlEntities = {       
        nbsp: ' ',       
        lt: '<',       
        gt: '>',       
        quot: '"',       
        amp: '&',       
        apos: '\''     
    };                
    return str.replace(/\&([^;]+);/g, function (match, key) {    
        if (key in htmlEntities) {            
            return htmlEntities[key];        
        }        
        return match;    
    });
}
console.log( unescapeHTML('&lt;div&gt;Blah blah blah&lt;/div&gt;') ); // => "<div>Blah blah blah</div>"

将HTML特殊字符转换成等值的实体

function escapeHTML (str) {    
    var escapeChars = {       
        '<' : 'lt',       
        '>' : 'gt',       
        '"' : 'quot',       
        '&' : 'amp',       
        '\'' : '#39'     

    };    
    return str.replace(new RegExp('[' + Object.keys(escapeChars).join('') +']', 'g'), function (match) {                        
        return '&' + escapeChars[match] + ';';    
    });
}
console.log( escapeHTML('<div>Blah blah blah</div>') ); // => "&lt;div&gt;Blah blah blah&lt;/div&gt";

将单词的首字符转换为大写

function titleize (str) {    
    return str.toLowerCase().replace(/(?:^|\s)\w/g, function (c) {        
        return c.toUpperCase();    
    });
}
console.log( titleize('my name is epeli') ); // => "My Name Is Epeli"

驼峰化

function camelize (str) {    
    return str.replace(/[-_\s]+(.)?/g, function (match, c) {        
        return c ? c.toUpperCase() : '';    
    });
}
console.log( camelize('-moz-transform') ); // => "MozTransform"

中划线化

function dasherize (str) {    
    return str.replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
}
console.log( dasherize('MozTransform') ); // => "-moz-transform"

实现模板引擎

function render(template, data) {
  const reg = /\{\{(\w+)\}\}/; // 模板字符串正则
  if (reg.test(template)) { // 判断模板里是否有模板字符串
    const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段
    template = template.replace(reg, data[name]); // 将第一个模板字符串渲染
    return render(template, data); // 递归的渲染并返回渲染后的结构
  }
  return template; // 如果模板没有模板字符串直接返回
}
let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let data = {
  name: '姓名',
  age: 18
}
render(template, data); // 我是姓名,年龄18,性别undefined

《JavaScript正则迷你书》链接 https://pan.baidu.com/s/1J_sVhmgZ94qXTr5c4hAItQ 4ki3