最常用的正则表达式(二)

1,798 阅读5分钟

1. Js 中关于正则的 API

1.1 String 中的方法

  • search

    search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。 如果没有找到任何匹配的子串,则返回 -1。

    var str="Mr. Blue has a blue house";
    console.log(str.search(/blue/i));
    // => 4
    // 注意 /i 表示对大小写忽略,所以找到了 Blue 的位置,即为 4
    
  • split

    split() 方法用于把一个字符串分割成字符串数组,接受的参数为字符串或正则表达式。

    var str="How are you doing today?";
    var n=str.split(/\s/);
    console.log(n);
    // =>  ["How", "are", "you", "doing", "today?"]
    
  • match

    match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配,接受的参数为 regexp

    注意:match 返回结果的格式,与正则对象是否有修饰符 g 有关。

    • 没有 g,返回的是标准匹配格式,即数组的第一个元素是整体匹配的内容,接下来是分组捕获的内容,然后是整体匹配的第一个下标,最后是输入的目标字符串。

    • g,返回的是所有匹配的内容。

    • 当没有匹配时,不管有无 g,都返回 null。

    var string = "2019/06/18";
    var regex1 = /\b(\d+)\b/;
    var regex2 = /\b(\d+)\b/g;
    console.log( string.match(regex1) );
    console.log( string.match(regex2) );
    // => ["2019", "2019", index: 0, input: "2019/06/18", groups: undefined]
    // => ["2019", "06", "18"]
    
  • replace

    replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。语法为 string.replace(regexp|substr, newSubStr|function)

    replace 有两种使用形式,因为它的第二个参数,可以是字符串,也可以是函数。

    • 当第二个参数是字符串时,我们可以用 $1,$2,...,$99 来匹配第 1-99 个分组里捕获的文本
    var result = "2,3,5".replace(/(\d+),(\d+),(\d+)/, "$3=$1+$2");
    console.log(result);
    // => "5=2+3"
    
    • 当第二个参数是函数时,在这种情况下,当匹配执行后,该函数就会执行。函数的返回值作为替换字符串。 注意:如果第一个参数是正则表达式,并且其为全局匹配模式,那么这个方法将被多次调用,每次匹配都会被调用。下面是该函数的参数。

      参数 含义
      match 匹配的子串
      $1, $2, ... 匹配的分组,对应于上例的$1,$2,...
      index 匹配到的子字符串在原字符串中的下标
      input 被匹配的原字符串

      如下例,匹配一个四位数字,把中间两位数字变成 **

    var result = "1234 2345 3456".replace(/(\d)\d{2}(\d)/g, function (match, $1, $2, index, input) {
        console.log([match, $1, $2, index, input]);
        return `${$1}**${$2}`
    });
    console.log(result);
    // => ["1234", "1", "4", 0, "1234 2345 3456"]
    // => ["2345", "2", "5", 5, "1234 2345 3456"]
    // => ["3456", "3", "6", 10, "1234 2345 3456"]
    // => 1**4 2**5 3**6
    

    image.png

1.2 RegExp 中对象方法

  • exec

    exec() 方法用于检索字符串中的正则表达式的匹配。如果字符串中有匹配的值返回该匹配值,否则返回 null。

    var str="Hello world!";
    var patt=/Hello/g;
    var result=patt.exec(str);
    console.log(result);
    // => ["Hello", index: 0, input: "Hello world!", groups: undefined]
    
  • test

    test() 方法用于检测一个字符串是否匹配某个模式。如果字符串中有匹配的值返回 true ,否则返回 false。

    var str="Hello world!";
    var patt=/Hello/g;
    var result=patt.test(str);
    console.log(result);
    // => true
    

2. 常用正则表达式

2.1 数字的千位符表示

情形:把一串整数转换成千位分隔形式,例如 12345678,转换成 12,345,678

思路:从个位往左数起,每三位前插入一个千位分隔符,即可以想象成我们要把每三位数字前面的空 ""(即位置)匹配出来,并替换成千位分隔符。

做法:首先因为需要从右往左匹配,$ 是必须要有的。三位数字用 \d{3},不确定多少组,用 (\d{3})+,所以目前为 /(\d{3})+$/g。 由于替换的是位置,所以需要用到位置锚 (?=p),即 /(?=(\d{3})+$)/g:

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

但如果是 9 位数字的话,

var result = "123456789".replace(/(?=(\d{3})+$)/g, ',')
console.log(result);
// => ,123,456,789

所以我们可以在匹配的位置前加一个非单词边界 \B, 即 /(?=(\B\d{3})+$)/g:

var result = "123456789".replace(/(?=(\B\d{3})+$)/g, ',')
console.log(result);
// => 123,456,789

image.png

2.2 模拟 trim 方法

情形:去掉字符串的开头和结尾的空白符

思路:还是匹配位置,替换成 ''

做法:

function trim(str) {
    return str.replace(/^\s+|\s+$/g, '');
}
console.log(trim("   test  ") );
// => test

image.png

2.3 单词首字母大写

情形:把 i'm a curious babe 转化成 I'm A Curious Babe

思路: 找到首字母并替换之

做法:

function upperTitle(str) {
    return str.replace(/(^|\s)\w/g, function(match) {
    return match.toUpperCase();
    })
}
console.log(upperTitle("i'm a curious babe"));
// => I'm A Curious Babe

image.png

驼峰化的思路是一样的:

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

image.png

2.4 验证身份证

情形: 15 或者 18 位身份证号,尾数可以是数字及 X 或者 x

做法:(^\d{15}$)|(^\d{17}(\d|X|x)$)

var reg = /(^\d{15}$)|(^\d{17}(\d|X|x)$)/;
var id = '25271618827172817X';
console.log(reg.test(id));
// => true

image.png

2.5 验证手机号

情形:以 1 开头,第二位数是 3/4/5/7/8 的 11 位手机号码

做法:^1[3,4,5,7,8,9]\d{9}$

image.png

2.6 验证邮箱

情形:以大写字母 [A-Z]、小写字母 [a-z]、数字[0-9]、下滑线_、减号-及点号.开头,并需要重复一次至多次[+]; 中间必须包括 @ 符号; @ 之后需要连接大写字母 [A-Z]、小写字母 [a-z]、数字 [0-9]、下滑线 _、减号 -及点号.,并需要重复一次至多次[+]; 结尾必须是点号 . 连接2至4位的大小写字母 [A-Za-z]{2,4}

做法:/^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/

var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
var email = 'test-babe@163.com';
console.log(reg.test(email));

image.png

2.7 验证密码

情形:密码长度 6-12 位,由数字、小写字母和大写字母组成,但必须至少包括 2 种字符。

思路1:密码长度6-12位,由 [\da-zA-Z]组成,可以写成 /^[\dA-Za-z]{6,12}$/; 至少包含数字,可以写成 /(?=.*\d)/

image.png

那么,至少包含两种字符就变成了 - 同时包含数字和小写字母 - 同时包含数字和大写字母 - 同时包含小写字母和大写字母 - 同时包含数字、小写字母和大写字母(这种情况被前三种情况包含)

做法1:所以最终写法为:/((?=.*\d)(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[\dA-Za-z]{6,12}$/

var regex = /((?=.*\d)(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[\dA-Za-z]{6,12}$/;

console.log(regex.test("1234567"));
console.log(regex.test("1234567AZ"));
console.log(regex.test("1234567AZx"));
// false
// true
// true

image.png

思路2:至少包含两种字符的意思就是说,不能全部都是数字,也不能全部都是小写字母,也不能全部都是大写 字母。 不能全部是数字的正则是:(?!^\d{6, 12}$)^[\da-zA-Z]{6,12}$

image.png

做法2:所以最终写法为:/(?!^\d{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[\dA-Za-z]{6,12}$/

var regex = /(?!^\d{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[\dA-Za-z]{6,12}$/;

console.log(regex.test("1234567"));
console.log(regex.test("1234567AZ"));
console.log(regex.test("1234567AZx"));
// false
// true
// true

image.png

主要参考来源: