下面是一个待匹配的内容:
http://q.cnblogs.com/test
q.cnblogs.com
cnblogs.com
www.baidu.com
www.sina.com
www.google.com
我想要匹配到的是同个Domain的Url 数量,当然上述的只是一个例子,Domain 不固定。
比如上面我想得到的Url数量为3
我需要不是仅仅匹配Url地址的,我需要的是匹配同一个Domain的
稍微修改一下样本,给域名之后加上斜杠,我想到的基于.net core的一种实现方式:
class Program
{
static void Main(string[] args)
{
var text = @"http://q.cnblogs.com/test
q.cnblogs.com/
cnblogs.com/
www.baidu.com/
www.sina.com/
www.google.com/";
var regex = new Regex(@"(?:[a-za-z0-9-]{1-50}[..])?([a-za-z0-9-]{1,20}[..][a-za-z]{2,4}(?:[..][a-za-z]{2})?)/");
var matches = regex.Matches(text);
var domains = matches.Select(m => m.Groups[1].Value);
var result = domains.GroupBy(x => x)
.Select(x => new { Domain = x.Key, Count = x.Count() })
.OrderByDescending(x => x.Count)
.FirstOrDefault();
Console.WriteLine($"{result.Domain}, {result.Count}");
//Output is cnblogs.com, 3
}
}
注:a-z
是为了匹配全角英文
获取domain时,需要进行Cast 转换:
var domains = matches.Cast<Match>().Select(m => m.Groups[1].Value);
PS: 这方法可比我存到 HashSet 里面简单许多。
@BUTTERAPPLE: 我这里测试不需要Cast,MatchCollection 实现了 IEnumerable<Match> 接口
@dudu: 新建了一个项目确实是不用Cast的,在现有项目中就死活下面这样:
'MatchCollection' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'MatchCollection' could be found
@dudu: 我知道了,使用netcoreapp2.0
是没问题的,使用netstandard2.0
就需要转换
@BUTTERAPPLE: 果然它们的MatchCollection
实现不一样
netstandard2.0:
public class MatchCollection : ICollection, IEnumerable
{ }
netcoreapp2.0:
public class MatchCollection : ICollection, IEnumerable, ICollection<Match>, IEnumerable<Match>, IList<Match>, IReadOnlyCollection<Match>, IReadOnlyList<Match>, IList
{ }
代码中需要判断匹配数为0的会出现的Object null 错误。
[^/,^\s]+?\.\S+?\.\S+?(?=/|\s)
凡是域名,都是 xxx.yyy.zzz这种格式,主域名为www居多,子域名就可多了。
你试试这个,绝对可以
如果只统计某个已知的域名,比如cnblogs.com 可以这样:
[^/,^\s]+?\.cnblogs\.com(?=/|\s)
如果,域名未知,可否有办法?
@BUTTERAPPLE:
未知域名就用 [^/,^\s]+?\.\S+?\.\S+?(?=/|\s)
[\da-zA-Z.]?Domain[/\da-zA-Z]?
特殊情况下可能会有问题,具体要看你的数据
匹配结果:
@nicky0227: 如果不提供Domain,是否有解决办法?
@BUTTERAPPLE: 很难吧,规律性不强,我举个例子:im.cat.com和www.im.cat 这两个url不是同一个Domain,但是均会被im.cat匹配
@nicky0227: 使用你的这个会,使用我下面回答的那个正则则不会。我就想一次性像把其匹配出来,好像还是要分几步。先把Url匹配出来,遍历结果加入到HashSet中,然后再进行操作。
使用这个可以^(?:http(?:s)?:\/\/)?(?:[^\.]+\.)?cnblogs\.com$
匹配如下
https://cnblogs.com
http://www.cnblogs.com
http://cnblogs.com
https://cnblogs.com
www.cnblogs.com
cnblogs.com
但是前提是我需要提供Domain!!
这个样本有些问题,如果出现 asp.net 算不算域名,如果是 url 的,总得有个路径,比如
– dudu 6年前q.cnblogs.com/
@dudu: 这个
– BUTTERAPPLE 6年前/
很关键,解决了我很多困惑。