一个正则表达式的问题

/^([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])|([a-zA-Z])$/.test('11a') // true

/^(([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])|([a-zA-Z]))$/.test('11a') // false

结果为什么不一样

这两个正则表达式的区别在于我在最外层增加了一个括号

阅读 3.1k
6 个回答

正则匹配结果不一样没有为什么,你说加了括号,你要明白括号的含义:对匹配结果进行分组

先来解释下正则的意思把 你好理解一点
分解一下
/^([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])|([a-zA-Z])$/
^([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])|([a-zA-Z])
输入字符串的开始匹配 满足([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])或者([a-zA-Z])其中一个条件
([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])|([a-zA-Z])$
输入字符串结束位置匹配 满足 ([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])或者([a-zA-Z])其中一个条件
具体一点
[a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9] 为a-zA-Z匹配一次||多次 为[A-Za-z0-9]匹配0次||多次
[a-zA-Z]这个就是a-zA-z 不多解释
() 匹配该结果并获取它

你上面加了()匹配结果那么就是先取或者|(可以理解为或者的意思'')的结果 则为左侧正则[a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9] 开头结尾均要满足它的匹配结果 才为true

我知道我来晚了 但是给你解释明白就好了 ?

开头的 ^ 和结尾的 $ 优先级都比 | 高,所以第一个例子其实是 | 分开的两段 ^([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])([a-zA-Z])$

可以记一下这个优先级

\                              转义符
(), (?:), (?=), []              圆括号和方括号
*, +, ?, {n}, {n,}, {n,m}      限定符
^, $, \任何元字符、任何字符    定位点和序列(即:位置和顺序)
|                              替换,"或"操作

我也来凑个热闹:

先来看下
/^([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])|([a-zA-Z])$/ 这个正则表达的含义
下面是正则铁路图
clipboard.png

从图中可以看到,只要匹配到以 group #1开始的字符串或者以group #2结束的字符就匹配成功。

那么从你测试的 "11a" 这个字符串来说,他正好满足了以 group #2 (匹配任意以字母结尾字符的字符串),所以被匹配。

再来看下,你加了括号的
/^(([a-zA-Z]+[A-Za-z0-9-]*[a-zA-Z0-9])|([a-zA-Z]))$/ 这个正则表达的含义

clipboard.png

字符串必须满足,以group #1开始,并以group #1匹配的结束

group #1 的匹配是包含俩个 或关系 的匹配,

所以第二个正则的匹配要求为,以 group #2 或 group #3 能匹配的内容开头,以group #2 或 group #3结尾

group #2 匹配 “字母[1-∞次] 字母|数字|横杠[0-∞次] 字母|数字[1次]” 这样一个字符串
group #3 匹配 “字母[1次]” 这样一个字符

group #2 没能命中你给的“11a”(因为group2 匹配的是字符串序列), 但是被group #3命中了a字符
clipboard.png

但是 group #3只命中了最后的尾字符,没有命中首字符 1,所以整个匹配就没有被匹配。

这个答案不知道够不够清楚啦。

我来一个简单粗暴的解释
第一个表示 以(group1)开头或者以(group2)结束的,
第二个表示 以(group1)开头或者以(group2)开头的

请看以下的案例:

let strs = ['1','2','12','10','02'];
let reg1 = /^1|2$/,
    reg2 = /^(1|2)$/;
strs.forEach(item =>{
    console.log((item+' ').slice(0, 2), reg1.test(item), reg2.test(item));
});

运行结果如下:

D:\temp>node test.js
1  true true
2  true true
12 true false
10 true false
02 true false

可以看到: reg1表示整个字符串以1开头以2结尾reg2表示整个字符串只能是1或2。可以理解为|$^优先级更低。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题