问题的来源
首先说一下引发我对这个正则中的中括号重新认识的问题吧。今天在读同事代码的时候,在做一个获取url最后的文件名时,他大概是这么写的

let name = url.match(/([^/]*).html?/)[1]

首先纠结的点是 [^/]* (后来发现是自己脑子不好使了),我理解成了匹配^或者/任意多次,但是结果name却是正确的,感觉世界崩塌了,怎么会这样?
然后去查菜鸟教程,原来中括号里^是排除的意思,然后觉得自己理解了这个正则的意思: 匹配一个字符串中不以/开头但是以.html结尾的最长的字符串。

但是再一看, 不对啊/([^/]*).html?/ 的前连个/不是已经配对成了一个正则了吗? 这不是语法错误吗? 什么鬼啊?

我的世界观又被颠覆了,难道中括号里的/是作为一个普通字符存吗吗?

然后我又试一试如下这些元字符:

js 正则test Js 正则 不能以中括号开头_元字符


元字符“.”不能匹配任何字符了,而是只能匹配自身,而且转移与否表现一致;

js 正则test Js 正则 不能以中括号开头_正则表达式_02


元字符“*”不转义也可以单独使用匹配自身;

js 正则test Js 正则 不能以中括号开头_元字符_03


其他的一些元字符也表现一样。

到此我终于可以下了一个结论:
任何元字符,只要放在中括号里,就只能代表字符本身,而不再具有其作为元字符的功能

在我验证这个结论的时候,使用了一些极端的例子,然后抛了一个错误:

js 正则test Js 正则 不能以中括号开头_正则_04


原来我的结论是有毛病的,“-”这个字符就比较有意思,它会根据自身前后来判断他的意义,如果“-”前后不是同时有字符,那么它就代表“-”本身,如果“-”前后都有字符,那么前后字符和“-”共同代表一个范围的字符,这个然后有“-”前后的ascii码决定。

上图中报错就是因为“-”前后有字符,但是因为“-”前的a的ascii码大于后面的A所有报错说:Range out of order in character class(字符顺序错误)。

当然上面的结论还有很多漏洞,比如 “^” 不是代表它本身,而是功能发生转变了,如果要在中括号里匹配 “^”, 就必须转义“\^”。