JavaScript正则表达式获取所有子域名

6

我有以下正则表达式:

[!?\.](.*)\.example\.com

并且这是一个示例字符串:

test foo abc.def.example.com bar ghi.jkl.example.com def

我希望正则表达式可以匹配以下内容:def.example.comjkl.example.com。我需要改变什么?它应该适用于 example.com 下的所有子域名。如果可能,它应该只匹配第一级子域名(abc.def.example.com -> def.example.com)。
regexpal上进行了测试,但并不完全有效 :( Screenshot

我认为你的意思是使用(?<!\.)而不是[!?\.](?<!)是一个负向先行断言,但很遗憾在Javascript中不被支持。[!?\.]将匹配!?.,基本上与(?:!|\?|\.)相同。 - HamZa
2个回答

10
您可以使用以下表达式:[^.\s]+\.example\.com解释
  • [^.\s]+:匹配除点号或空格之外的任何字符一次或多次。
  • \.example\.com:匹配example.com
请注意,您无需在字符类中转义句点。

太棒了,谢谢!我该如何通过JavaScript在字符串中获取此正则表达式的所有匹配项?str ='test abc.def.example.com and ghi.jkl.example.com usw.'; str.match('[^.\s]+\.example\.com');只显示了一个匹配项... - fnkr
2
@fnkr 添加一个 g 标志(表示全局):str.match(/[^.\s]+\.example\.com/g) => 没有引号,但是斜杠和一个在正则表达式定界符 / 外的 g替换子字符串也适用相同的规则 - Elias Van Ootegem
1
@fnkr: str.match(/[^.\s]+\.example\.com/g); 返回一个数组 [def.example.com, jkl.example.com] - Elias Van Ootegem

4
仅作为侧面说明,虽然HamZa的答案适用于您当前的示例代码,但如果您需要确保域名也是有效的,则可能需要尝试不同的方法,因为[^.\s]+将匹配任何不是空格或.的字符(例如,该正则表达式将将jk&^%&*(l.example.com作为“有效”的子域进行匹配)。
由于域名值的有效字符远少于无效字符,因此您可以考虑对正则表达式使用“加法”方法,而不是减法。这个模式可能是您要寻找的有效域名:/(?:[\s.])([a-z0-9][a-z0-9-]+[a-z0-9]\.example\.com)/gi 进一步分解:
- (?:[\s.]) — 匹配标记最低级子域名开始的空格或. - ([a-z0-9][a-z0-9-]+[a-z0-9]\.example\.com) — 捕获一组字母、数字或破折号,必须以字母或数字开头和结尾(域名规则),然后是example.com域名。 - gi — 使正则表达式模式具有贪婪和大小写不敏感性。
现在,问题就在于获取匹配项。由于.match()与正则表达式“非捕获组”不兼容,所以改用.exec()
var domainString = "test foo abc.def.example.com bar ghi.jkl.example.com def";
var regDomainPattern = /(?:[\s.])([a-z0-9][a-z0-9-]+[a-z0-9]\.example\.com)/gi;
var aMatchedDomainStrings = [];
var patternMatch;

// loop through as long as .exec() still gets a match, and take the second index of the result (the one that ignores the non-capturing groups)          
while (null != (patternMatch = regDomainPattern.exec(domainString))) {
    aMatchedDomainStrings.push(patternMatch[1]);
}

此时,aMatchedDomainStrings 应包含所有有效的一级子域名。

var domainString = "test foo abc.def.example.com bar ghi.jkl.example.com def";

...应该得到:def.example.comjkl.example.com,而:

var domainString = "test foo abc.def.example.com bar ghi.jk&^%&*(l.example.com def";

您只需输入以下命令即可获取def.example.com


1
我不想破坏气氛,但请注意域名支持的内容远不止字母、数字和连字符。例如,请看这个域名 http://aa®.com,还有像 http://سجل.السعودية 这样的UTF8域名:p - HamZa
1
@HamZa - 不确定我们是否真的想在这个问题的评论部分讨论DNS vs. IDNA。 :) 最终,不过,这仍然不会改变我的观点...与其允许除空格或 . 之外的任何字符(这肯定会允许无效的域字符),如果他想要匹配有效性,他将需要识别他想要允许的字符并相应地设置模式匹配...他想使用DNS还是IDNA标准由他决定。 ;) - talemyn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接