Go to comments

Souffle js 正则表达式笔记

渡一教育公开课笔记

正则表达式 Regular Expression 在 js 代码中简写为 regexp,

重点它是一个表达式,正则是表达式的修饰词,整体的意思是符合一个规则的表达式,

主要作用是对字符串进行操作、过滤、以及检索校验的一种规则


一、定义和匹配

“正则表达式”的定义有两种方式

1. 直接字面量 /abc/

2. 构造函数 new RegExp('abc')


正则表达式匹配使用的两个方法

1. 正则表达式上的方法 reg.test(str)

2. 字符串上的方法 str.match(reg)


示例,

通过一个“用户名规则的校验”体验正则表达式是如何定义和匹配的,比如输入的用户名必须以数字、字母、下划线,这三种之一开头

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>用户名的校验规则</title>
</head>
<body>

<input type="text" id="username"/>
<div id="msg"></div>

<script>

  var username = document.getElementById('username');
  var msg = document.getElementById("msg");

  username.oninput = function(){
    checkedFun(this.value);
  }

  function checkedFun(str){
    var reg = /^[\dA-z_]/;
    if(str.match(reg)){
      msg.innerText = "符合规则";
    }else{ 
      msg.innerText = "用户名只能以数字、字母、下划线开头";
    }
  }
  
</script>
</body>
</html>


监听 oninput 输入事件,每次输一个字符都会触发,

获取 input 框输入的值是一个字符串,正则表达式对输入的字符串进行校验


 ^[\dA-z_] 

^ 表示以方括号里面的字符开头

[] 方括号代表一个字符,这一个字符可以是数字 \d,可以是字母 A-z,也可以是划线 _


str.match(reg)

使用字符串上的 match 方法实现正则的匹配

1. 输入 abc 匹配成功,返回的是符合规则的的子字符串 ['a', index: 0, input: 'abc', groups: undefined]

2. 输入空格或中文返回 null,表示不符合匹配规则


 用构造函数 RegExp 的方式声明正则表达式,参数传的字符串是匹配规则

function checkedFun(str){
  var reg = new RegExp('^[\\da-zA-Z_]');
  if(reg.test(str)){
    msg.innerText = "符合规则";
  }else{ 
    msg.innerText = "用户名只能以数字、字母、下划线开头";
  }
}


注意,

 new RegExp('^[\\dA-z_]') 

参数是字符串,

在字符串中 \ 斜杠有特殊的含义,表示转义后面的一个字符,

要想实现 \d 的效果,要在加一个斜杠 \\d 转义一下,表示取消后面第二个 \ 斜杠的含义


reg.text(str)

正则表达式上的匹配方法

1. 参数是要校验的字符串,校验字符串是否符合正则规则

2. 返回一个布尔值


体验一些匹配规则

/[3578]$/        $表示以中括号里面的数字3578,任何一个结尾都可以

/[3578]+$/     量词 + 号代表 1 ~ 多个(* 代表 0 ~ 多个),匹配 3578,1 至多个数字结尾

/^[3578]+$/   以 3578 开头又以 3578 结尾,输入 3、35、358 等都可以匹配,有一个不是 3578 的字符都是错误

/3578/            字符串中含一个这样 "3578" 的整体


Ps:

input 元素是行级块元素,既可以设置宽高也不会占满一行,

修改一下 .msg 元素 display: inline-block 就到一行了


二、原子

什么是原子?

组成正则表达式的最小单位就是原子


原子表

语法描述
[abc]方括号内的任意一个字符
[^abc]不在方括号内的字符
[0-9]0-9 之间的数字
[a-z]任何小写字母
[A-Z]任何大写字母
[A-z]大写和小写字母
()子表达式
\uxxx查找十六进制数 xxx 规定的 Unicode 字符
[\u4e00-\u9fa5]所有中文字符
参考图片连接


方括号跟小括号的区别

[ \dA-z_ ]   代表一个字符,方括号里面的内容是或的关系,任意一个字符可以是数字、可以是字母、可以是下划线

( \dA-z_ )   并列的关系,要匹配的,先是数字,后面是字母,最后是下划线(小括号也叫子表达式)


模式修饰符

修饰符
i代表 ignorecase 忽略大小写
m代表 multiline 多行匹配
g代表 global 全局匹配,匹配出所有符合规则的子字符串


三、元字符

语法描述
.代表单个字符,除了换行符和行结束符以外的任意一个字符
\w小写 w 表示字母、数字、下划线,等价于 [A-Za-z0-9_]
\W非单词字符,就是除了小 \w 以外的字符
\d数字
\D非数字
\s空白字符
\S非空白字符
\b单词边界
\B非单词边界符
\n换行符
\f换页符
\r回车符
\t制表符
\v垂直字表符


. 点

正则表达式中“点”有特殊的含义,它表示任意一个字符,

除了换行符和行结束符以外,其他的任意一个字符

换行符是 \n,行结束符就是回车 \r,也就是说 \n 和 \r 它匹配不出来


 /.ello/ 

点 . 代表第一个字符,以任意一个字符开始

然后后面必须是 ello

修饰符 g 全局匹配,表示把所有符合条件的全部匹配出来

var str = "hello world, hello duyi, welcome duyi";

var reg = /.ello/g;

console.log(str.match(reg)); // ['hello', 'hello']


字符串的 match 方法,返回所有符合条件的“子字符串”是一个数组的形式

加了修饰符 g 返回的是数组

如果没有加 g 返回的是类数组

var str = "hello world, hello duyi, welcome duyi";

var reg = /.ello/;

console.log(str.match(reg)); // ['hello', index: 0, input: 'hello world, hello duyi, welcome duyi', groups: undefined]

[

  0: "hello" 匹配成功的字符片段

  groups: undefined  groups代表一个组,这个组代表一个子表达式,没有子表达式就是 undefined

  index: 0 当前匹配成功的索引值

  input: "hello world, hello duyi, welcome duyi" 我们要匹配的整个字符串

  length: 1

]


点 . 不能匹配换行符 \n 和结束符 \r,可以匹配出制表符 \t

var str = "第一行 \nello world, \rello duyi, \tello lizi";

var reg = /.ello/g;

console.log(str.match(reg)); // ['\tello']


alert(str) 弹框里面可以看到换行符、回车符的效果分成了三行,制表符的是一个空白

第一行

ello world, 

ello duyi, ello lizi


\w

小写 w 代表 26 个大小英文的字母、数字、下划线,

单纯的一个 \w 返回了所有的英文字符,但不包括空格、制表符、换行符、行结束符,逗号

var str = "\rello world, \nello duyi, \tello lizi";

var reg = /\w/g;

console.log(str.match(reg)); // ['e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', 'e', 'l', 'l', 'o', 'd', 'u', 'y', 'i', 'e', 'l', 'l', 'o', 'l', 'i', 'z', 'i']


如果想要拆分单词怎么办呢?

可以通过元字符和量词结合的方法,

量词就是元字符的个数,比如 + 加号表示匹配前一个字符的 1 至 多个字符


 \w+ 

元字符 \w 结合量词 +,返回的是字符串中一个一个的单词,去掉了逗号、空格、制表符

var str = "hello world, hello duyi, welcome duyi \tello";

var reg = /\w+/g;

console.log(str.match(reg)); // ['hello', 'world', 'hello', 'duyi', 'welcome', 'duyi', 'ello']


正则表达式的规则,一般都会遵循“贪婪匹配”

就是越多越好,所以量词 + 号是有几个就匹配几个,不是返回单个的字母了


 \w* 

* 星号代表 0 至 多个,也就是说没有的也能给匹配出来,

匹配出好多个空位,代表 0 个英文字符,还有空逗号、制表符都匹配成空位了

var str = "hello world, hello duyi, welcome duyi \tello";

var reg = /\w*/g;

console.log(str.match(reg)); // ['hello', '', 'world', '', '', 'hello', '', 'duyi', '', '', 'welcome', '', 'duyi', '', '', 'ello', '']


\W

大写 W 代表非单词字符,匹配所有的空格、逗号、制表符(就是除了字母、数字、下划线以外的

var str = "\rello world, \nello \tduyi";

var reg = /\W/g;

console.log(str.match(reg)); // ['\r', ' ', ',', ' ', '\n', ' ', '\t']

0: "\r"

1: " "

2: ","

3: " "

4: "\n"

5: " "

6: "\t"


\d

小写 d 代表数字,每一个数字,一个一个的都匹配出来了

var str = "hello world123, hello456 duyi, welcome duyi \tello132323";

var reg = /\d/g;

console.log(str.match(reg)); // ['1', '2', '3', '4', '5', '6', '1', '3', '2', '3', '2', '3']


配合量词 + 号,匹配出连着的数字

var str = "hello world123, hello456 duyi, welcome duyi \tello132323";

var reg = /\d+/g;

console.log(str.match(reg)); // ['123', '456', '132323']


\D

大写 D 代表非数字,配合量词 + 号,除数字以外的其他字符都匹配出来了

var str = "hello world123, hello456 duyi, welcome duyi \tello132323";

var reg = /\D+/g;

console.log(str.match(reg)); // ['hello world', ', hello', ' duyi, welcome duyi \tello']

相当于数字充当了分割符

0: "hello world"

1: ", hello"

2: " duyi, welcome duyi \tello"


\s

小写 \s 表示空白字符,其实就是空格包含 \r、\n、\t

var str = "hello world\r, hello duyi, \nwel comeduyi\t";

var reg = /\s/g;

console.log(str.match(reg)); // [' ', '\r', ' ', ' ', ' ', '\n', ' ', '\t']
console.log(str.match(reg).length); // 8


配合量词 + 号,\n 连着前面的空格

var reg = /\s+/g;

console.log(str.match(reg)); // [' ', '\r', ' ', ' ', ' \n', ' ', '\t']
console.log(str.match(reg).length); // 7


\S

大写 S 非空白字符,匹配出没有 \r、\n、\t

var str = "hello world, hello duyi,\r welcome \nduyi \tello132323";

var reg = /\S+/g;

console.log(str.match(reg)); //  ['hello', 'world,', 'hello', 'duyi,', 'welcome', 'duyi', 'ello132323']


\b

匹配单词边界每一个单词有两个边界,七个单词有14个空白

var str = "hello world, hello duyi,\r welcome \nduyi \tello";

var reg = /\b/g;

console.log(str.match(reg)); // ['', '', '', '', '', '', '', '', '', '', '', '', '', '']


单词边界和空格的区别

1. 空格是有字符的

2. 整个字符如果连着 -hello- 左右两边是单词边界,也就是说一个单词有两个边界


\B

非单词边界就是两个挨着的字母之间

var str = "hello world";

var reg = /\B/g;

console.log(str.match(reg)); // ['', '', '', '', '', '', '', '']


非单词边界就 h-e-l-l-o 字母之间

var str = "hello";

var reg = /\b/g;
console.log(str.replace(reg, '-')); // -hello-

var reg = /\B/g;
console.log(str.replace(reg, '-')); // h-e-l-l-o


非单词边界有什么用,

详看下面的练习部分“给 10000000000 每三个 0 打一个点变成 10.000.000.000”


四、量词

量词是修饰前面一个字符的个数,就是你想匹配多少个

量词描述
n+1次多次
n*0次1次多次
n?0次1次
n{x}前一个字符n固定的个数
n{x,y}代表一个范围
n{x,}
n$匹配以n结尾的字符串
^n任何以n开头的字符串
?=n正向肯定预查,m(?=n)  匹配任何后面紧接着指定字符串 n 的字符串
?!n正向否定预查,m(?!n)  匹配后面不是 n 的 m
?<=n反向肯定预查,(?<=n)m 匹配前面是 n 的 m
?<!n反向否定预查,(?<!n)m 匹配前面不是 n 的 m


上面用到的量词 + 号和 * 号,

都是至多匹配,有多少就拿多少,也就是贪婪匹配的原则


?

问号是至少匹配,只匹配 0 或 1 个,可以取消贪婪匹配


把英文字母一个一个的拿出来,只取字母不要空格,正常的做法是

1. 全局 g 匹配,把全部符合的都匹配出来

2. [A-z] 包括大小写字母

3. 字符串的 match 方法返回一个数组

var str = "hello world";

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

console.log(str.match(reg)); // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']


加上量词 + 号表示 1 次至多次,可以匹配出字符串中的两个单词,

这是正则的贪婪匹配的效果,能匹配多就不匹配少,有多少符合条件的都匹配出来,作为一个字符串

var str = "hello world";

var reg = /[A-z]+/g;

console.log(str.match(reg)); // ['hello', 'world']


加上 ? 问号,

表示至少匹配,是最少能拿几个,非贪婪匹配能少就不多,匹配结果又是一个一个的字母了

var str = "hello world";

var reg = /[A-z]+?/g;

console.log(str.match(reg)); // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']


{}

花括号里面只传一个数字,表示的是固定的个数,比如 3 个3个的进行匹配

var str = "hello world";

var reg = /[A-z]{3}/g;

console.log(str.match(reg)); // ['hel', 'wor']


2 个字符 2 个字符的进行匹配

var str = "hello world";

var reg = /[A-z]{2}/g;

console.log(str.match(reg)); // ['he', 'll', 'wo', 'rl']


如果花括号里面写两个数字,表示的是一个范围,

比如   {2,4}   范围是 2 ~ 4 个之间,贪婪匹配原则有多就不匹配少,4个4个的匹配出来

var str = "hello world";

var reg = /[A-z]{2,4}/g;

console.log(str.match(reg)); // ['hell', 'worl']


注意,

两个数字  {2,   4}  之间是逗号隔开,并且不能有空格

var str = "hello world";

var reg = /[A-z]{2, 4}/g;

console.log(str.match(reg)); // null


  {2,   4}   之间有空格,就把它当字符了,中间就是空格的字符,不是一个范围了

var str = "hello world{2, 4}"; // 把{2, 4}写到这

var reg = /[A-z]{2, 4}/g;

console.log(str.match(reg)); // ['d{2, 4}']


把 {2,4} 放到字符里面,有空格就不是范围了,就当做字符匹配了

var str = "hello world{2, 4}";

var reg = /[A-z]{2, 4}/g;

console.log(str.match(reg)); // ['d{2, 4}']


[^A-z]

^在方括号里面不代表以某个字符开头了,代表除了中扩号里面以内的其他字符

var str = "hello world{2, 4}";

var reg = /[^A-z]/g;

console.log(str.match(reg)); // [' ', '{', '2', ',', ' ', '4', '}']


?=

 m(?=n)  正向肯定预查,匹配后面紧跟着 n 的字符串 m

详看下面的练习部分“给 10000000000 每三个 0 打一个点变成 10.000.000.000


?!

正向否定预查,和正向肯定相对应的,就是后面不跟着某一个字符(正向否定预查用的不是很多),

 a(?!d)  我们想匹配的是 a,但条件是 a 后面不能是 d,

修饰符 g 全局匹配出所有的,

字符串里面有三个 a,匹配出后面两个 a

var str = "adkhfalskdfa";

var reg = /a(?!d)/g;

console.log(str.match(reg)); // ['a', 'a']


?<=

反向肯定预查, (?<=f)a  我们想匹配 a ,条件是前面是 f 后面的那个 a

var str = "adkhfalskdfa";

var reg = /(?<=f)a/g;

console.log(str.match(reg)); // ['a', 'a']


?<!

反向否定预查,(?<!f)a  匹配的是 a,但是 a 的前面不能是 f,所以只有第一个 a 满足条件

var str = "adkhfalskdfa";

var reg = /(?<!f)a/g;

console.log(str.match(reg)); // ['a']


注意,

预查必须要加小括号括起来,

但是一定要区分开,

因为我们知道,通过小括号括起来的就是子表达式

预查这里比较特殊,小括号里面是预查的,它就不代表子表达式了


 /m(?<!f)a/g 

课堂提问,前面加上一个 m,

代表前面是一个 m,

后面的 a 的特点是,前面不跟着 f,

也就是 m 后面不是 f,然后在后面是 a,

预查只是特点,它 (?<!f) 不是匹配的项,

该课堂提问,有点陷进预查了,这样写没有什么意义,直接写 /ma/g 就可以了


五、子表达式

子表达式有很多功能,需要我们去探索,


1、反向引用

提取出三个相同连续重复的字符,比如 aaa、bbb、eee

/\w{3}/ 相当于 /(\w\w\w)/,每个 \w 有自己的范围,它的范围是字母、数字、下划线其中任意的一个字符,最后一个 dde 不符合要求

var str = "aaabbbddeee";

var reg = /\w{3}/g;

console.log(str.match(reg)); // ['aaa', 'bbb', 'dde']


 (\w)\1 

子表达式可以拿到正则表达式中的一部分单独匹配,并将匹配成功的结果在整个正则表示中重复引用

\1  是反向引用,数字 1 是子表达式的编号,代表引用第一个子表达式匹配出来的内容,

就是把子表达式匹配的内容拿出来用,所以匹配的内容跟第一个表达式相同

var str = "aaabbbddeee";

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

console.log(str.match(reg)); // ['aa', 'bb', 'dd', 'ee']


 (\w)\1\1 

匹配三个相同的字符,就写两个 \1\1 反向引用,

第一个字符是第一个子表达式 (\w)

这两个 \1\1 都是第一个子表达式里面匹配成功的字符

var str = "aaabbbddeee";

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

console.log(str.match(reg)); // ['aaa', 'bbb', 'eee']


2、字符串 replace 替换方法

子表达式的“反向引用”在字符串替换方法 replace 里面的应用

1. 参数一传是正则表达式 reg,会把满足正则的位置的字符进行替换

2. 如果参数二传递的是固定的字符串,会把符合匹配规则的部分进行替换

var str = "aaabbbddeee";

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

console.log(str.replace(reg, '*')); // **dd*


replace 方法的第二个参数还可以传一个回调函数,

1. 该函数可以接收一些参数,通过打印 arguments 看到函数的形参

2. 函数 return 返回的内容,就是匹配成功的字符,要要替换的新内容

var str = "aaabbbddeee";

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

str.replace(reg, function(){
  console.log(arguments);
});

// Arguments(4) ['aaa', 'a', 0, 'aaabbbddeee', callee: ƒ, Symbol(Symbol.iterator): ƒ]
// Arguments(4) ['bbb', 'b', 3, 'aaabbbddeee', callee: ƒ, Symbol(Symbol.iterator): ƒ]
// Arguments(4) ['eee', 'e', 8, 'aaabbbddeee', callee: ƒ, Symbol(Symbol.iterator): ƒ]

因为匹配成功三次,所以打印了三次,每一次打印的是一个数组

[

  0: aaa, 是整个字符串,匹配成功的字符

  1: a, 第一个子表达式 (\w),匹配成功的内容

  2: 0, 是一个索引值,当前匹配成功的位置

]


传三个形参,分别打印出来

var str = "aaabbbddeee";

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

str.replace(reg, function(param1, param2, param3){
  console.log(param1, param2, param3);
});

// aaa a 0
// bbb b 3
// eee e 8


3、反向引用应用,字符串去重

  /(\w)\1+/ 

(\w) 先匹配一个字母,\1 第二个字母和子表达式匹配的相同,+ 然后可能有很多个这样的字母,只要重复的都匹配出来了

var str = "Aaadddoooooooobbeee";

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

console.log(str.match(reg)); // ['Aaa', 'ddd', 'oooooooo', 'bb', 'eee']


接下来就替换重复的字符,

回调函数里面 return 的内容,就是替换的内容,

意思是第二个参数 param2 是子表达式 (\w) 匹配成功的内容,它就一个字符,直接返回第二个参数 param2 就可以了

var str = "Aaadddoooooooobbeee";

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

var result = str.replace(reg, function(param1, param2, param3){
  return param2;
});

console.log(result); // Adobe

去掉修饰符 i 就可以区分大小写了 Aadobe


课堂提问,

如果是两个 /1,替换重复 3 次的字符,

比如中间 8 个字母 o,三个三个的被替换后变成两个o,加上剩下的两个 o,所以结果是四个 o

var str = "Aaadddoooooooobbeee";

var reg = /(\w)\1\1/gi;

var result = str.replace(reg, function(param1, param2, param3){
  return param2;
});

console.log(result); // Adoooobbe


4、replace 方法替换示例,高亮显示

做一个搜索关键词高亮显示效果,

原理就是给第一个参数 param1 加一个高亮样式后返回

正则表达式拼接关键词后是一个字符串,用 RegExp 方式的参数传的是字符串,所以用它定义正则表达式

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>搜索关键词高亮</title>
<style>
</style>
</head>
<body>

<script>
 
var str = '<span style="color:#999">快乐的池塘里面,有一只小青蛙,跳啊跳啊跳</span>';

var pond = '池塘';
var frog = '小青蛙'
var jump = '跳';

var keywords = `(${pond}|${frog}|${jump})`;

var reg = new RegExp(keywords, 'g');

var result = str.replace(reg, function(param1, param2, param3){
  return `<span style="color:#008c8c">${param1}</span>`;
});

document.body.innerHTML = result;

</script>
</body>
</html>


六、练习

1、拆分 url

通过子表达式,对整个 url 字符串各个部分,进行依次的匹配

var str = "https://www.baidu.com/s?tn=68018901_3_dg&ie=UTF-8&wd=flash";
var str = "https://www.bilibili.com/video/BV1qpCfY5Eaz/?spm_id_from=333.788.player.player_end_recommend_autoplay&vd_source=30698713e5e2b66f66e6fa017646273c#dsd";
var str = "http://127.0.0.1:8848/js%E6%96%B9%E6%B3%95%E6%95%B4%E7%90%86/text.html";

var reg = /(http|https):\/\/([\w\.]+)(:\d*)?(\/?[\w\/\.%-]*)\??([\w=\.&]+)?#?(.*)?/mig;

// console.log(reg.exec(str));

var arr = reg.exec(str);

var querys = {};

if(arr[5]){
  var _arr = arr[5].split("&");
  for(var i = 0; _arr.length > i; i++){
    var s = _arr[i].split("=");
    // console.log(s)
    querys[s[0]] = s[1];
  }
}

console.log(arr);

var obj = {
  protocol: arr[1],
  origin: arr[2], 
  port: arr[3], 
  path: arr[4], 
  query: querys
};

console.log(obj);


/(http|https):\/\/

协议以 http 或 https 开头,

冒号后面的两个斜线 / 在正则表达式中有特殊含义,和正则表达式起始符 / 重复了,要用反 \ 斜线转义


/(http|https):\/\/([\w\.]+)/

域名规则是由多个字母、点、数字组成,

\w 表示字母和数字

正则表达式里面“点”代表单个字符,除换行和行结束符以外的所有字符,也需要用反斜杠转义

+ 号表示1至多个


/(http|https):\/\/([\w\.]+)(:\d*)?/  可以不要最后一个?号

端口号由冒号和多个数字组成,

: 冒号可以 0 次 1 或  1 次

\d+  加号的意思是,1至多个数字,然后 ? 也是 0次 1次


/(http|https):\/\/([\w\.]+)(:\d*)?\/?([\w\/\.%-]*)/

路径可能有英文字符、-、点、中文、斜杠、中文(中文部分转义后有 %),

abc.com/ 域名后面的斜线是路径,有时候默认不显示,所以可以出现 0 次,

路径是多个英文字符,也可能没有,所以用量词 *


/(http|https):\/\/([\w\.]+)(:\d*)?\/?([\w\/\.%-]*)\??([\w=&]+)?/mig

参数部分以 ? 号开头,? 号是量词也需要转义


使用 exec 方法匹配返回的是类数组

[0] 是整个正则表达式匹配成功的内容

[1] 第一个子表达式匹配的内容

[2] 第二个子表达式

[3] ...... 从左往右数,如果有嵌套的小括号,从外往里依次的数


2、给 10000000000 每三个 0 打一个点变成 10.000.000.000(面试题 2 )

我们要匹配的“非单词边界”有一个特点,它后面跟着的是三个数字

先写 \d{3} 代表三个连续的数字 \d\d\d

量词里面有一个“正向预查”?=n

m(?=n) 匹配后面紧跟着 n 的 m,意思是后面的 n 是条件,最后匹配出的是前面的 m。后面的 n 三个数字,前面的 m 是非单词边界

var str = "10000000000";

var reg = /\B(?=\d{3})/;

console.log(str.replace(reg, ".")); // 1.0000000000


全局匹配,发现有点不对

var str = "10000000000";

var reg = /\B(?=\d{3})/g;

console.log(str.replace(reg, ".")); // 1.0.0.0.0.0.0.0.000

1.0000000000 第一个非单词边界的位置,后面跟着三个数字

1.0.000000000 第二个非单词边界的位置,后面跟着三个数字

1.0.0.00000000 第三个非单词边界的位置,后面跟着三个数字

1.0.0.0.0000000 依次类推

1.0.0.0.0.000000

1.0.0.0.0.0.00000

1.0.0.0.0.0.0.0000

1.0.0.0.0.0.0.0.000 匹配结果


我们需要的是从后往前,每三位数字打一个点

需要加 $ 符号表示从后往前

现在我们匹配的是,以三个数字结尾的单词边界 10000000.000

var str = "10000000000";

var reg = /\B(?=\d{3}$)/g;

console.log(str.replace(reg, ".")); // 10000000.000


想再往前面接着每三个数字打一个点,就是3的倍数6

{3} 是量词,+号也是量词,

所以前面的 \d{3} 要加一个小括号和 + 隔开

var str = "10000000000";

var reg = /\B(?=(\d{3})+$)/g;

console.log(str.replace(reg, ".")); // 10.000.000.000


(?=..)  问号后面等于/大于/小于的时候,都需要扩上括号

+?      只有问号在量词后面的时候,不需要加括号,代表非贪婪匹配


3、统一空格(面试题 6 )

去掉多余的空格

var str = "Regexp    remove    string spaces";

var reg = /( )+/g;

console.log(str.replace(reg, ' ')); // Regexp remove string spaces


4、把 the-first-name 转换成小驼峰 theFirstName(面试题 4 )

var str = "the-first-name";

// var reg = /(?<=-)\w/gi;
var reg = /-\w/gi;

var result = str.replace(reg, function(a, b, c){
  // console.log(a, b, c);
  return str[b+1].toUpperCase();
});

console.log(result); // theFirstName


5、附,面试题

1. 正则表达式实现aabb的形式变成bbaaa

2. 给 10000000000 每三个 0 打一个点变成 10.000.000.000

3. 字符串去重 aaaaaaabbbbcccc 变成 abc

4. 把 the-first-name 转换成小驼峰 theFirstName

5. 匹配结尾的数字

6. 统一空格

7. 判断字符串是不是由数字构成

8. 删除字符串中的空格

9. 身份证号匹配

10. 将字符串

"select student.*, result.* from student inner join result on student.id = result.studentid"

和"select * from student"

中的 student 替换成 key 值



刚刚,一个人咳嗽,都已经习以为常了,

不过 2025-05-23 15:17 我字符串处理的能力又提高了,重要的是熟练了,目前比较满意



Leave a comment 0 Comments.

Leave a Reply

换一张