Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript正则表达式 #9

Open
CruxF opened this issue Sep 2, 2018 · 0 comments
Open

JavaScript正则表达式 #9

CruxF opened this issue Sep 2, 2018 · 0 comments

Comments

@CruxF
Copy link
Owner

CruxF commented Sep 2, 2018

一、前言

该博文源自慕课网的《JavaScript正则表达式》课程。老师讲的生动有趣,由浅入深,是一门好课程。为了让自己更好记忆和继续深究正则表达式,因此写下该篇博文。下面推荐两个实用的在线网站:
正则表达式工具
代码及时响应在线网站

二、实例化正则对象

在JavaScript中,一共有两种方法实例化正则对象,下面请看具体的方法。

1、 字面量:var reg = /\bis\b/g;
【注意】
\b代表单词边界,g代表全文进行匹配。如果没有\b和g,会怎么样呢?请动手分别进行测试一下,下面给出测试模板,内容可自行更改。
测试:'he is a boy,This is a dog'.replace(reg,'IS');

2、 构造函数:var reg = new RegExp('\\bis\\b','g');
【注意】
在构造函数中,我们需要\来进行转义。
测试:'he is a boy,This is a dog'.replace(reg,'IS');

三、修饰符

在JavaScript正则表达式中,一共有三种修饰符,分别是一下三种。
1、 g:global 全文搜索,假如不添加的话,那么搜索到第一个匹配即停止;
测试:'He is a boy,she is here?'.replace(/\bis\b/g,'0');

2、 i:ignore case 忽略大小写,默认大小写敏感;
测试:'He is a boy,she IS here?'.replace(/\bis\b/gi,'0');

3、 m:multiple lines 多行搜索。
测试:'@123\n@234\n@345'.replace(/^@\d/gm,'Q');

四、元字符

JavaScript正则表达式中,元字符非常之多,下面我们一起来耐心看看。

1、 \s:匹配单个空格,等同于[\f\n\r\t\v];而\S则恰恰相反,它匹配的是非空格字符。

测试:/\s.+/.exec('This is a test String.');
【分析】
其中.含义是除了回车符和换行符之外的所有字符,+含义是出现一次或多次(至少出现一次),exec() 方法用于检索字符串中的正则表达式的匹配。假如有点晕,再来看看下面的栗子

var regs = /\s.+/
var str = "this is dog stil here"
// thishaha
 console.log(str.replace(regs,"haha"))

【应用场景】
匹配任意空或空白字符,如果你什么也没输入,或输入的只有空格、回车、换行等字符,则匹配成功。这样就可以验证用户是否正确输入内容了。
【用法】

var  reg=/^\s*$/;
if(reg.test(value)){
  alert('请输入有效值');
  return false;
}

【分析】
其中^含义是以什么为开始,*含义是出现零次或多次(任意次),$含义是以什么为结束,test() 方法用于检测一个字符串是否匹配某个模式.

2、 \w:表示单词字符,等同于字符集合[a-zA-Z0-9_];而\W表示非单词字符,等效于[^a-zA-Z0-9_]。

var reg = /\w+/;
var str='fengxiong';
alert(reg.exec(str));

【分析】
返回完整的fengxiong字符串,因为所有字符都是单词字符。

var reg = /\w+/;
var str='.className';
alert(reg.exec(str));

【分析】
结果显示匹配了字符串中的className,只有第一个“.”唯一的非单词字符没有匹配。

var reg = /\w+/;
var str='正则教程';
alert(reg.exec(str));

【分析】
试图用单词字符去匹配中文自然行不通了,返回 null。

var reg = /\W+/;
var str='正则教程';
alert(reg.exec(str));

【分析】
返回完整的字符串,因为,中文算作是非单词字符。

3、其他元字符
\f:匹配换页符;
\n:匹配换行符;
\r:匹配回车符;
\t:匹配制表符;
\v:匹配垂直制表符;
\d:匹配数字;
\D:匹配非数字;
\b:匹配单词边界;
\B:匹配非单词边界

来个测试题:将符合一个ab+数字+任意字符的字符串代替为B。
答案:'ab32432dab2,'.replace(/ab\d./g,'B');

五、重要元字符

1、^:
可以用来创建反向类/负向类,也就是不属于某类的内容,比如:
'a1b2c3d4'.replace(/[^abc]/g,'X');

又有以什么为开头的含义,比如:
'1 fafs'.replace(/^\d\s/g,'Q');

2、[ ]
可以用来构建一个简单的类,也就是几个字符归纳为集合,比如:
'a1b2c3d4'.replace(/[abc]/g,'X');

可以使用[a-z]来连接两个字符表示从a到z的任意字符,比如:
'a1b2d3x4z9'.replace(/[a-z]/g,'A');

在[]组成的类内部是可以连写的,比如:
'a1b2d3x4z9B7A3N4M8'.replace(/[a-zA-Z]/g,'J');

如何在[]把-给算上呢?其实只要把-加在后面即可,比如:
'2018-01-14'.replace(/[0-9-]/g,'A');

六、量词

?:出现零次或一次(最多出现一次);
+:出现一次或多次(至少出现一次);
*:出现零次或多次(任意次);
{n}:出现n次;
{n,m}:出现n到m次;
{n,}:至少出现n次。

八、分组

1、使用()可以达到分组的功能,使用量词作用于分组,比如:
'a1b2c3d4'.replace(/([a-z]\d){3}/g,'X');
'BoyGirl'.replace(/Boy|Girl/g,'X');
'BoyGirlBoyBorl'.replace(/Boy(Gi|Bo)rl/g,'X');

2、分组的反向引用,比如,将2018-01-14 转换为 01/14/2018,对比下面两段代码的结果:
'2018-01-14'.replace(/\d{4}-\d{2}-\d{2}/g,'$2/$3/$1');
'2018-01-14'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$2/$3/$1');

八、贪婪模式与非贪婪模式

1、贪婪模式:尽可能多的匹配,比如:
'12345678'.replace(/\d{3,6}/g,'X');

2、非贪婪模式:让正则表达式尽可能少的匹配,也就是说一旦成功匹配则不再继续尝试,比如:
'12345678'.replace(/\d{3,6}?/g,'X');

九、正则表达式训练营

1、用正则匹配手机号码

function tele(tel) {
  if (tel.search(/^1[34578]\d{9}$/g) > -1) {
    console.log("1");
  } else {
    console.log("0");
  }
}
tele("13456799014");

【分析】
寻找以13、14、15、17或18开头,以9个数字结尾的字符,找到了就返回1,失败就返回0。search()方法去匹配字符串,如果匹配成功,就返回匹配成功的位置,如果匹配失败就返回-1

还有一种更加简便的方法:

function tele(tel) {
  return /^1[34578]\d{9}$/g.test(tel);
}
console.log(tele("13456799014"));

【分析】
test()方法的返回值是布尔值,通过该值可以匹配字符串中是否存在于正则表达式相匹配的结果,如果有匹配内容,返回ture,如果没有匹配内容返回false。
【拓展】
match()方法去匹配字符串,如果匹配成功,就返回匹配成功的数组,如果匹配不成功,就返回null;
replace()方法去匹配字符串,匹配成功的字符去替换新的字符串。

2、判断字符串是否包含了数字

function contain(str) {
  var reg = /\d/g;
  return reg.test(str);
}
console.log(contain("fds3af"));

3、给定字符串str,检查其是否包含连续重复的字母,包含返回true,否则返回false。

function contain(str) {
   return /([a-zA-Z])\1/.test(str);
}
console.log(contain("fdsaaf"));

【分析】
"小括号包含的表达式所匹配到的字符串" 不仅是在匹配结束后才可以使用,在匹配过程中也可以使用。表达式后边的部分,可以引用前面 "括号内的子匹配已经匹配到的字符串"。引用方法是 "/" 加上一个数字。"/1" 引用第1对括号内匹配到的字符串,"/2" 引用第2对括号内匹配到的字符串……以此类推,如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 "(" 在前,那这一对就先排序号。

4、判断是否以元音字母结尾。

function contain(str) {
  return /[a,e,i,o,u]$/i.test(str);
}
console.log(contain("fdsaaa"));

5、给定字符串str,检车其是否包含3个连续的数字

function contain(str) {
  return str.match(/\d{3}/g);
}
console.log(contain("1g556777"));

6、判断是否符合指定格式(正确格式示例:556-142-7489)

function contain(str) {
  return /^(\d{3}-){2}\d{4}$/g.test(str);
}
console.log(contain("235-894-5623"));

【解析】
以3个数字加“-”开头,并且重复2次,最后为4个数字。

7、待处理
写一个正则表达式,匹配 ""

let str = '<OPTION  value="待处理">待处理</OPTION>';
let regExp = /^<.*?>/g;
console.log(regExp.exec(str)[0]); 

【分析】
以<开头,匹配除了回车符合换行符之外的所有字符,出现任意次,出现零次或一次,这就匹配到了所有的字符。exec()方法返回一个匹配项的数组,而match()方法返回所有匹配项组成的数组。

8、如何获取一个字符串中的数字字符,并按数组形式输出,如:
dgfhfgh254bhku289fgdhdy675gfh输出[254,289,675]

let str = 'dgfhfgh254bhku289fgdhdy675gfh';
let regExp = /\d+/g;
console.log(str.match(regExp));

【分析】
+含义是出现一次或多次(至少出现一次)。

9、敏感词过滤

let str = '我草你妈哈哈背景天胡景涛哪肉涯剪短发欲望';
let regExp = /草|肉|欲|胡景涛/g;
let result = str.replace(regExp,"*");
console.log(result);

以上的是缩减版,下面来个完整版的:

let str = '我草你妈哈哈背景天胡景涛哪肉涯剪短发欲望';
let regExp = /草|肉|欲|胡景涛/g;
let result = str.replace(regExp, function (match) {
  let len = match.length;
  let str;
  switch (len) {
    case 1:
      str = '*';
      break;
    case 2:
      str = "**";
      break;
    case 3:
      str = "***";
      break;
    default:
      str = '****';
  }
  return str;
});
console.log(result); //我*你妈哈哈背景天***哪*涯剪短发*望

10、让2013-6-7 变成 2013.6.7

let str = '2013-6-7';
let regExp = /-/g;
console.log(str.replace(regExp, '.')); //2013-6-7

11、给定这样一个连字符串,写一个function转换为驼峰命名法形式的字符串 getElementById

var s1 = "get-element-by-id";
function camelCased(str) {
  let regExp = /-(\w)/g;
  str.replace(regExp, function(match, p) {
      return p.toUpperCase();
   })
}
camelCased(s1);

【分析】
\w代表的是单词字符

12、判断字符串中是否包含数字

let str1 = 'abc9efh';
let str2 = 'abcefg';
let regExp = /\d/;
console.log(regExp.test(str1)); // true
console.log(regExp.test(str2)); // false

13、判断连续重复字母

let str1 = 'abc3d4e5';
let str2 = 'aab2c3';
let regExp = /([a-zA-Z])\1/;
console.log(regExp.test(str1));//false
console.log(regExp.test(str2));//true

14、给定字符串 str,检查其是否包含 3 个连续的数字

  • 如果包含,返回最新出现的 3 个数字的字符串
  • 如果不包含,返回 false
let str1 = 'abc123efg';
function captureThreeNumbers(str) {
    let res;
    if (res = str.match(/\d{3}/)) {
        return res[0];
    } else {
        return false;
    }
}
console.log(captureThreeNumbers(str1)); //123

15、给定字符串 str,检查其是否符合美元书写格式

  • 以 $ 开始
  • 整数部分,从个位起,满 3 个数字用 , 分隔
  • 如果为小数,则小数部分长度为 2
  • 正确的格式如:$1,023,032.03 或者 $2.03,错误的格式如:$3,432,12.12 或者 $34,344.3
let regExp = /^\$\d{1,3}(,\d{3})*(\.\d{2})?$/;
console.log(regExp.test('$1.23')); //true
console.log(regExp.test('$111.23')); //true 
console.log(regExp.test('$1111.23')); //false
console.log(regExp.test('$1,123.23')); //true

【分析】
以$开头,匹配数字符1到3个;匹配逗号(,)再匹配3个数字符,该规则出现零次或多次(即任意次);匹配句号(.),再匹配2个数字符,该规则出现零次或一次,并在结尾处。

16、对人口数字的格式化处理,三位数字用一个','(逗号)隔开

function numberWithCommas(x) {
    //对右侧人口数字的格式化处理,三位数字用一个','(逗号)隔开
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
console.log(numberWithCommas(12345678))//12,345,678

【分析】
非单词边界,匹配右边有三个数字符的数(正向前瞻),匹配一次或者多次;匹配负向前瞻。

17、将单词is替换为IS

let str = 'English poetry is one of their great heritages';
console.log(str.replace(/\bis\b/,'IS'));
// English poetry IS one of their great heritages

18、实现数字转千分位

var reg = /\d{1,3}(?=(\d{3})+$)/g;
var str = "1234556789";
console.log(str.replace(reg,"$&,"));

【分析】
数字千分位的特点是:第一个逗号后面数字的个数是3的倍数,正则:/(\d{3})+$/;第一个逗号前最多可以有1至3个数字,正则:/\d{1,3}/。加起来就是/\d{1,3}(\d{3})+$/,?=含义是零宽度正预测先行断言,具体用法自行百度^_^
【其他】

var reg = /\d{1,3}(?=(\d{3})+$)/g;
var str = 1234556789;
console.log(str.toString().replace(reg,"$&,"));

十、参考文章

由于正则表达式真的是难以灵活运用和讲清楚,因为它实在是太强大了,只有不断的训练自己,多看并多练才有可能完全掌握它,下面提供一些参考文章。

面试系列:关于正则表达式
正则表达式面试题
一些正则表达式的随记
正则表达式总结1
从面试到正则
正则表达式总结2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant