如何在 C# 中使用正则表达式从字符串中提取域名?

Posted

技术标签:

【中文标题】如何在 C# 中使用正则表达式从字符串中提取域名?【英文标题】:How to Extract Domain name from string with Regex in C#? 【发布时间】:2021-09-16 04:59:36 【问题描述】:

我想用正则表达式从字符串中提取***域名和国家***域名。我测试了许多像这样的代码的正则表达式:

var linkParser = new Regex(@"\b(?:https?://|www\.)\S+\b", RegexOptions.Compiled | RegexOptions.IgnoreCase);
Match m = linkParser.Match(Url);
Console.WriteLine(m.Value);

但是这些代码都不能正确地做到这一点。 用户输入的文本字符串可以是以下语句:

jonasjohn.com
http://www.jonasjohn.de/snippets/csharp/
jonasjohn.de
www.jonasjohn.de/snippets/csharp/
http://www.answers.com/article/1194427/8-habits-of-extraordinarily-likeable-people
http://www.apple.com
https://www.cnn.com.au
http://www.downloads.news.com.au
https://ftp.android.co.nz
http://global.news.ca
https://www.apple.com/
https://ftp.android.co.nz/
http://global.news.ca/
https://www.apple.com/
https://johnsmith.eu
ftp://johnsmith.eu
johnsmith.gov.ae
johnsmith.eu
www.jonasjohn.de
www.jonasjohn.ac.ir/snippets/csharp
http://www.jonasjohn.de/
ftp://www.jonasjohn.de/
https://subdomain.abc.def.jonasjohn.de/test.htm

我测试的正则表达式:

^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/\n]+)"

\b(?:https?://|www\.)\S+\b

://(?<host>([a-z\\d][-a-z\\d]*[a-z\\d]\\.)*[a-z][-a-z\\d]+[a-z])

还有太多 我只需要域名,不需要协议或子域。 喜欢: Domainname.gTLD 或 DomainName.ccTLD 或 DomainName.xyz.ccTLD

我从PUBLIC SUFFIX得到了他们的名单

当然,我在 ***.com 上看过很多帖子,但没有一个回复我。

【问题讨论】:

如果你有Uri,为什么还要使用正则表达式? this回答解决了吗? 试试\b(?:(https?:\/\/|www\.)?)\S+\b @LeiYang 您是否根据 OP 的可能输入示例列表检查了这一点? @Fildor 我在一些在线测试仪中试过,你认为哪一行不匹配? 【参考方案1】:

您不需要正则表达式来解析 URL。如果你有一个有效的 URL,你可以使用 Uri 构造函数之一或Uri.TryCreate 来解析它:

if(Uri.TryCreate("http://google.com/asdfs",UriKind.RelativeOrAbsolute,out var uri))

    Console.WriteLine(uri.Host);

www.jonasjohn.de/snippets/csharp/jonasjohn.de/snippets/csharp/ 虽然不是有效的 URL。 TryCreate 仍然可以将它们解析为相对 URL,但读取 Host 会抛出 System.InvalidOperationException: This operation is not supported for a relative URI.

在这种情况下,您可以使用UriBuilder 类来解析和修改 URL,例如:

var bld=new UriBuilder("jonasjohn.com");
Console.WriteLine(bld.Host);

打印出来

jonasjohn.com

设置 Scheme 属性会生成一个有效的完整 URL:

bld.Scheme="https";
Console.WriteLine(bld.Uri);

这会产生:

https://jonasjohn.com:80/

【讨论】:

听起来不错,但是如果您输入“jonasjohn.com”之类的错误,则会出现一个问题:相对 URI 不支持此操作。 @Feri 使用什么代码? UriBuilder 有效。至于 Uri,我已经解释过这不起作用,因为......为什么假设这是一个域而不是相对 Url 的第五部分? jonasjohn.com 不是有效 URL,但它是 有效 相对 URL。 http://mysite/jonasjohn.com 是一个有效的 URL。 http://mysite 也是如此【参考方案2】:

根据Lidqy的回答,我写了这个函数,我认为支持大部分可能的情况,如果输入的值不在这个范围内,可以让它异常。

public static string ExtractDomainName(string Url)
        
            var regex = new Regex(@"^((https?|ftp)://)?(www\.)?(?<domain>[^/]+)(/|$)");

            Match match = regex.Match(Url);

            if (match.Success)
            
                string domain = match.Groups["domain"].Value;
                int freq = domain.Where(x => (x == '.')).Count();
                while (freq > 2)
                
                    if (freq > 2)
                    
                        var domainSplited = domain.Split('.', 2);
                        domain = domainSplited[1];
                        freq = domain.Where(x => (x == '.')).Count();
                    
                
                return domain;
            
            else
            
                return String.Empty;
            
        

【讨论】:

【参考方案3】:
var rx = new Regex(@"^((https?|ftp)://)?(www\.)?(?<domain>[^/]+)(/|$)");
var data = new[]            "jonasjohn.com",
                             "http://www.jonasjohn.de/snippets/csharp/",
                             "jonasjohn.de",
                             "www.jonasjohn.de/snippets/csharp/",
                             "http://www.answers.com/article/1194427/8-habits-of-extraordinarily-likeable-people",
                             "http://www.apple.com",
                             "https://www.cnn.com.au",
                             "http://www.downloads.news.com.au",
                             "https://ftp.android.co.nz",
                             "http://global.news.ca",
                             "https://www.apple.com/",
                             "https://ftp.android.co.nz/",
                             "http://global.news.ca/",
                             "https://www.apple.com/",
                             "https://johnsmith.eu",
                             "ftp://johnsmith.eu",
                             "johnsmith.gov.ae",
                             "johnsmith.eu",
                             "www.jonasjohn.de",
                             "www.jonasjohn.ac.ir/snippets/csharp",
                             "http://www.jonasjohn.de/",
                             "ftp://www.jonasjohn.de/",
                             "https://subdomain.abc.def.jonasjohn.de/test.htm"
                         ;

        foreach (var dat in data) 
            var match = rx.Match(dat);
            if (match.Success)
                Console.WriteLine("0 => 1", dat, match.Groups["domain"].Value);
            else 
                Console.WriteLine("0 => NO MATCH", dat);
            
        

【讨论】:

感谢您回答它在某些方面工作但不能像这样“subdomain.abc.def.jonasjohn.de/test.htm” Afaics 在 .com 或 .co 之后添加 2 个字母的后缀的约定仅限于 .uk、.nz、.au 以及其他一些英联邦域,因此请尝试以下操作:@"^((https?|ftp)://)?(www\.)?[\w\.]*?(?&lt;domain&gt;\w+\.\w+)(\.(uk|au|nz|ir|ae))?(/|$)"

以上是关于如何在 C# 中使用正则表达式从字符串中提取域名?的主要内容,如果未能解决你的问题,请参考以下文章

外壳脚本。如何使用正则表达式提取字符串

我无法理解如何在 c# 中使用正则表达式或如何解决我的问题

从给定字符串中提取 url 的 C# 正则表达式模式 - 不是完整的 html url,而是裸链接

C#正则表达式如何提取一段字符串中汉字后的数字

使用正则表达式 C# 从字符串中获取十进制值

在 C# 中使用正则表达式从完整路径解析文件名