如何用正则匹配可选内容?解决贪婪匹配导致的正则失效问题
嘿帕特里克,这个问题我太熟了!贪婪模式确实是正则里的“坑王”之一,你遇到的问题本质就是.*这个贪婪匹配会把所有内容(包括本应属于端口前缀的冒号)一股脑吃掉,导致后面的组根本没机会匹配。
别担心,咱们换个思路就能搞定——把贪婪的.*改成非贪婪的.*?,再调整一下分组逻辑就能完美适配你要的三种格式。
最终正则表达式
^(.*?)(?::(\d*))?$
拆解一下每个部分的作用:
^和$:锚定整个字符串,确保我们匹配的是完整的URI,不会只匹配中间片段。(.*?):非贪婪捕获组,用来匹配主机部分(不管是域名、IPv4还是带括号的IPv6)。非贪婪模式会“见好就收”,一旦后面的可选冒号+端口部分能匹配,它就会立刻停止,绝不会吃掉后面的冒号。(?::(\d*))?:这是一个可选的组合组,专门处理端口相关的情况:::匹配端口前的冒号(\d*):捕获端口数字,允许空字符串(对应host.domain.com:这种只有冒号没端口的情况)?:让整个冒号+端口部分变成可选,完美适配不带端口的host.domain.com格式
测试一下所有场景:
host.domain.com→ 第一组:host.domain.com,第二组:空(无端口)host.domain.com:→ 第一组:host.domain.com,第二组:空(只有冒号)host.domain.com:443→ 第一组:host.domain.com,第二组:443[ab:cd::0]:22→ 第一组:[ab:cd::0],第二组:221.2.3.4:22→ 第一组:1.2.3.4,第二组:22
如果你想严格限制端口是合法的数字范围(1-65535),可以把(\d*)改成(\d{1,5}),不过记得后续还要做数值验证,因为\d{1,5}也能匹配99999这种无效端口哦。
内容的提问来源于stack exchange,提问作者patrik
相关产品推荐
相关产品推荐

