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

原来正则表达式我记得这么少 #9

Open
baiyuze opened this issue Feb 25, 2019 · 0 comments
Open

原来正则表达式我记得这么少 #9

baiyuze opened this issue Feb 25, 2019 · 0 comments

Comments

@baiyuze
Copy link
Owner

baiyuze commented Feb 25, 2019

前言

记得上一次系统的学习正则表达式,还是刚学前端的事,现在过去那么久了,现在有必要将正则给补一补,也许这一次会有不同的感悟。

正则的速查表

字符 详细
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n"匹配字符"n"。"\n"匹配一个换行符。串行"\\"匹配"\"而"\("则匹配"("。
^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo*能匹配“z"以及"zoo"。*等价于{0,}
+ 匹配前面的子表达式一次或多次。例如,“zo+"能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。
? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配"does"或"does"中的"do"。?等价于{0,1}
{n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配"Bob"中的"o",但是能匹配"food"中的两个o
{n,} n是一个非负整数。至少匹配n次。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。
{n,m} mn均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,"o{1,3}"将匹配"fooooood"中的前三个o。"o{0,1}"等价于"o?"。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串"oooo","o+?"将匹配单个"o",而"o+"将匹配所有"o"。
. 匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。
(pattern) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”。
(?:pattern) 匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“`(
(?=pattern) 正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“`Windows(?=95
(?!pattern) 正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“`Windows(?!95
(?<=pattern) 反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“`(?<=95
(?<!pattern) 反向否定预查,与正向否定预查类拟,只是方向相反。例如“`(?<!95
x|y 匹配xy。例如,“`z
[xyz] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“p”。
[a-z] 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n"或"\r"之前的位置。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx 匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Za-z之一。否则,将c视为一个原义的“c”字符。
\d 匹配一个数字字符。等价于[0-9]
\D 匹配一个非数字字符。等价于[^0-9]
\f 匹配一个换页符。等价于\x0c\cL
\n 匹配一个换行符。等价于\x0a\cJ
\r 匹配一个回车符。等价于\x0d\cM
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]
\S 匹配任何非空白字符。等价于[^ \f\n\r\t\v]
\t 匹配一个制表符。等价于\x09\cI
\v 匹配一个垂直制表符。等价于\x0b\cK
\w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。
\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
\xn 匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。.

|
| \num | 匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。 |
| \n | 标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。 |
| \nm | 标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若nm均为八进制数字(0-7),则\nm将匹配八进制转义值nm。 |
| \nml | 如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。 |
| \un | 匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。 |

使用正则表达式的方法

方法 描述
exec 一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回null)。
test 一个在字符串中测试是否匹配的RegExp方法,它返回true或false。
match 一个在字符串中执行查找匹配的String方法,它返回一个数组或者在未匹配到时返回null。
search 个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。
replace 一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。
split 一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的String方法。

当你想要知道在一个字符串中的一个匹配是否被找到,你可以使用testsearch方法;想得到更多的信息(但是比较慢)则可以使用execmatch方法。如果你使用execmatch方法并且匹配成功了,那么这些方法将返回一个数组并且更新相关的正则表达式对象的属性和预定义的正则表达式对象(详见下)。如果匹配失败,那么exec方法返回null(也就是false)。

var myRe = /d(b+)d/g;
var myArray = myRe.exec("cdbbdbsbz");

输出:

["dbbd", "bb", index: 1, input: "cdbbdbsbz", groups: undefined]
  • ["dbbd", "bb"] 匹配到的字符串和所有被记住的子字符串。

  • index 在输入的字符串中匹配到的以0开始的索引值。

  • input 初始字符串。

  • lastIndex 下一个匹配的索引值。(这个属性只有在使用g参数时可用在 通过参数进行高级搜索 一节有详细的描述.)

  • source 模式文本。在正则表达式创建时更新,不执行。

使用括号的子字符串匹配

一个正则表达式模式使用括号,将导致相应的子匹配被记住。例如,/a(b)c /可以匹配字符串“abc”,并且记得“b”。回调这些括号中匹配的子串,使用数组元素[1],……[n]

使用括号匹配的子字符串的数量是无限的。返回的数组中保存所有被发现的子匹配。下面的例子说明了如何使用括号的子字符串匹配。

下面的脚本使用replace()方法来转换字符串中的单词。在匹配到的替换文本中,脚本使用替代的$ 1,$ 2表示第一个和第二个括号的子字符串匹配。

var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr);

输出结果:

Smith, John

通过标志进行高级搜索

正则表达式有四个可选参数进行全局不分大小写搜索。这些参数既可以单独使用也可以一起使用在任何顺序和包含正则表达式的部分中。

标志 描述
g 全局搜索
i 不区分大小写搜索
m 多行搜索
y 执行“粘性”搜索,匹配从目标字符串的当前位置开始,可以使用y标志。

例子

给一个连字符串例如:get-element-by-id转化成驼峰形式。

var str = "get-element-by-id";
var reg = /-\w/g;
str.replace(reg, (val) => {
    return val.slice(1).toUpperCase();
});
//"getElementById"

匹配二进制数字

  • 方法一
var str = "10101111";
var reg = /^[01]+$/g;
console.log(reg.test(str));
  • 方法二
var str = "81";
var reg = /^(?!0)\d+$/;
console.log(reg.test(str));
  • 方法三
var str = "0101212312";
var reg = /^[^0]\d+$/g;
console.log(reg.test(str));
//false

分割数字每三个以一个逗号划分

var str = "12345678901";
function numSplit(str){
    var re = /(\d)(?=(\d{3})+$)/g;
    //(\d{3})+$ 的意思是连续匹配 3 个数字,且最后一次匹配以 3 个数字结尾。
    //要找到所有的单个字符,这些字符的后面跟随的字符的个数必须是3的倍数,并在符合条件的单个字符后面添加,
    return str.replace(re,'$1,');
}
console.log(numSplit(str));//12,345,678,901

如何获取一个字符串中的数字字符,并按数组形式输出

var str="dgfhfgh254bhku289fgdhdy675";
var re=/(\d+)/g;
console.log(str.match(re));

求一串字符串中出现次数最多的字符和其出现的次数

var str = "qjvj58h7vv9n57v55v5jj";
var n = -1;
while ((new RegExp("(.)(.*?\\1){"+(++n)+"}")).test(str));
console.log("出现次数最多的字符是 "+RegExp.$1+",出现次数 "+n);

解释一下

  • .代表任意一个字符。
  • (.)选择任意一个字符进行复制。
  • .* 代表任意一个字符后面有0个或者多个字符。
  • (.)(.*\\1)是否存在一个或多个字符与它相同。
  • (.)(.*?\\1)表示是非贪婪模式。
  • \1匹配和正则表达式中的括号(计算左括号)中出现相同内容的内容,数字代表匹配第几个括号。
  • \\1代表第一个圆括号里面的内容是否相同。

压缩字符串(例如:abcbc压缩后依然是abcbc,而xxxyyyyyyz压缩后就是3x6yz)

var str = "xxxyyyyyyz";
str = str.replace(/(.)\1+/ig,function(s,a){return s.length+a;});
console.log(str);
  • i不区分大小写

判断是否含有连续字符

var str = 'a2s3s2d2d3dsfas';
var reg = /(\w)\1/ig
console.log(reg.test(str));

匹配一个字符串中的正浮点数

var reg = /(0.\d+)|(\d+.\d+)/; 
console.log(reg.test('0'));  // false
console.log(reg.test('0.5'));  // true
console.log(reg.test('d0.5'));  // true
console.log(reg.test('d0.5s'));  // true
console.log(reg.test('d0.a5s'));  // false

最后

如果有地方不合理的,麻烦提出来一下

参考文章:

js正则表达式常见面试题
【大家一起来思考】近段时间整理的...
js正则表达式常见面试题
MDN

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