【问题标题】:Regular expression to retrieve domain.tld检索 domain.tld 的正则表达式
【发布时间】:2010-10-26 04:27:03
【问题描述】:

我需要一个 Java 中的正则表达式,我可以使用它从任何 url 检索 domain.tld 部分。所以https://foo.com/barhttp://www.foo.com#barhttp://bar.foo.com 都会返回 foo.com。

我写了这个正则表达式,但它匹配整个 url

Pattern.compile("[.]?.*[.x][a-z]{2,3}");

我不确定我是否匹配“。”性格对。我试过了 ”。”但我从 netbeans 收到一个错误。

更新:

tld 不限于 2 或 3 个字符,http://www.foo.co.uk/bar 应返回 foo.co.uk。

【问题讨论】:

  • 实际上不是完全重复的,因为另一个问题试图删除 tld 部分以及一些二级部分,如“.co.uk”。但唯一的区别是你是否捕捉到了那部分。我猜他希望foo.co.uk 给 foo.co.uk
  • 您知道有四个字母的顶级域名,如“信息”和“名称”吗?我认为您错过了这一点,因为您的正则表达式中有“{2,3}”。其次,如果你想匹配点,你必须像这样“\\。”
  • 刚刚读到甚至还有“.museum”和“.travel” tlds。
  • 我发现这个答案非常有用:stackoverflow.com/a/4820675/1740705.

标签: java regex


【解决方案1】:

这比您想象的要难。您的示例 https://foo.com/bar 中有一个逗号,它是一个有效的 URL 字符。这是一篇关于一些麻烦的精彩帖子:

https://blog.codinghorror.com/the-problem-with-urls/

https?://([-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|])

是一个很好的起点

“掌握正则表达式”中有关此主题的一些列表:

http://regex.info/listing.cgi?ed=3&p=207

@sjobe

>>> import re
>>> pattern = r'https?://([-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|])'
>>> url = re.compile(pattern)
>>> url.match('http://news.google.com/').groups()
('news.google.com/',)
>>> url.match('not a url').groups()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'groups'
>>> url.match('http://google.com/').groups()
('google.com/',)
>>> url.match('http://google.com').groups()
('google.com',)

对不起,这个例子是用python而不是java,它更简短。 Java 需要对正则表达式进行一些无关的转义。

【讨论】:

  • 我不认为他的意思是逗号是网址的一部分,他只是分隔一个列表
  • 这就是我的意思,它是模棱两可的。正则表达式应如何确定逗号是否是 URL 的一部分?
  • 无论如何都没关系,因为他对 http URL 的“domain.tld”部分感兴趣。那部分没有逗号。
  • 我尝试了那个正则表达式[在末尾添加了一个')'] https?://([-A-Za-z0-9+&@#/%?=~_() |!:,.;]*[-A-Za-z0-9+&@#/%=~_()|]) 但它不匹配任何网址。我正在尝试“news.google.com”和“google.com
  • 您的编码恐怖链接已损坏。我猜是这个。 blog.codinghorror.com/the-problem-with-urls
【解决方案2】:

我会使用 java.net.URI 类来提取主机名,然后使用正则表达式来提取主机 uri 的最后两部分。

import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RunIt {

    public static void main(String[] args) throws URISyntaxException {
        Pattern p = Pattern.compile(".*?([^.]+\\.[^.]+)");

        String[] urls = new String[] {
                "https://foo.com/bar",
                "http://www.foo.com#bar",
                "http://bar.foo.com"
        };

        for (String url:urls) {
            URI uri = new URI(url);
            //eg: uri.getHost() will return "www.foo.com"
            Matcher m = p.matcher(uri.getHost());
            if (m.matches()) {
                System.out.println(m.group(1));
            }
        }
    }
}

打印:

foo.com
foo.com
foo.com

【讨论】:

  • 这实际上是我最终做的。
  • 像 foobar.co.uk 这样的域名呢?
【解决方案3】:

如果字符串包含有效的 URL,那么您可以使用正则表达式,例如(Perl 引用):

/^
(?:\w+:\/\/)?
[^:?#\/\s]*?

(
[^.\s]+
\.(?:[a-z]{2,}|co\.uk|org\.uk|ac\.uk|org\.au|com\.au|___etc___)
)

(?:[:?#\/]|$)
/xi;

结果:

url: https://foo.com/bar
matched: foo.com
url: http://www.foo.com#bar
matched: foo.com
url: http://bar.foo.com
matched: foo.com
url: ftp://foo.com
matched: foo.com
url: ftp://www.foo.co.uk?bar
matched: foo.co.uk
url: ftp://www.foo.co.uk:8080/bar
matched: foo.co.uk

对于 Java,它会被引用如下:

"^(?:\\w+://)?[^:?#/\\s]*?([^.\\s]+\\.(?:[a-z]{2,}|co\\.uk|org\\.uk|ac\\.uk|org\\.au|com\\.au|___etc___))(?:[:?#/]|$)"

当然,您需要替换 etc 部分。

示例 Perl 脚本:

use strict;

my @test = qw(
    https://foo.com/bar
    http://www.foo.com#bar
    http://bar.foo.com
    ftp://foo.com
    ftp://www.foo.co.uk?bar
    ftp://www.foo.co.uk:8080/bar
);

for(@test){
    print "url: $_\n";

    /^
    (?:\w+:\/\/)?
    [^:?#\/\s]*?

    (
    [^.\s]+
    \.(?:[a-z]{2,}|co\.uk|org\.uk|ac\.uk|org\.au|com\.au|___etc___)
    )

    (?:[:?#\/]|$)
    /xi;

    print "matched: $1\n";
}

【讨论】:

  • 我忘记对字符串开头的第一个 \w 进行双重转义,应该是“\\w”。如果您看到任何其他单反斜杠转义它们。
  • 我在谷歌上搜索了大约一个小时,发现你的答案最适合我的情况。谢谢。但是java regex String 好像有点问题,应该是这样的 "^(?:\\w+://)?[^:?#/\\s]*?([^.\\s]+ \\.(?:[az]{2,}|co\\.uk|org\\.uk|ac\\.uk|org\\.au|com\\.au|com.cn|___etc___) )(?:[:?#/].*|$)"
【解决方案4】:

new URL(url).getHost()

不需要正则表达式。

【讨论】:

  • 很好,但在高吞吐量循环中不起作用:)
【解决方案5】:

您将需要获取所有可能的 TLD 和 ccTLD 的列表,然后与它们进行匹配。您必须这样做,否则您将永远无法区分 subdomain.dom.com 和 hello.co.uk。

所以,给你自己一个这样的清单。我建议将其反转以便存储,例如 uk.co。 然后,您可以通过获取 // 和 / 或行尾之间的所有内容来从 URL 中提取域。分裂于 。并向后工作,匹配 TLD,然后再增加 1 个级别以获取域。

【讨论】:

    【解决方案6】:
        /[^.]*\.[^.]{2,3}(?:\.[^.]{2,3})?$/
    

    差不多了,但是当二级域名有3个这样的字符时不匹配:www.foo.com 测试一下here

    【讨论】:

      【解决方案7】:

      这对我有用:

      public static String getDomain(String url){
          if(TextUtils.isEmpty(url)) return null;
          String domain = null;
          if(url.startsWith("http://")) {
              url = url.replace("http://", "").trim();
          } else if(url.startsWith("https://")) {
              url = url.replace("https://", "").trim();
          }
          String[] temp = url.split("/");
          if(temp != null && temp.length > 0) {
              domain = temp[0];
          }  
          return domain;
      }
      

      【讨论】:

        【解决方案8】:

        代码:

        public class DomainUrlUtils {
            private static String[] TLD = {"com", "net"}; // top-level domain
            private static String[] SLD = {"co\\.kr"}; // second-level domain
        
            public static String getDomainName(String url) {
                Pattern pattern = Pattern.compile("(?<=)[^(\\.|\\/)]\\w+\\.(" + joinTldAndSld("|") + ")$");
                Matcher match = pattern.matcher(url);
                String domain = null;
        
                if (match.find()) {
                    domain = match.group();
                }
        
                return domain;
            }
        
            private static String joinTldAndSld(String delimiter) {
                String t = String.join(delimiter, TLD);
                String s = String.join(delimiter, SLD);
        
                return new StringBuilder(t).append(s.isEmpty() ? "" : "|" + s).toString();
            }
        }
        

        测试:

        public class DomainUrlUtilsTest {
        
            @Test
            public void getDomainName() throws Exception {
                // given
                String[][] domainUrls = {
                    {
                        "test.com",
                        "sub1.test.com",
                        "sub1.sub2.test.com",
                        "https://sub1.test.com",
                        "http://sub1.sub2.test.com"
                    },
                    {
                        "https://domain.com",
                        "https://sub.domain.com"
                    },
                    {
                        "http://domain.co.kr",
                        "http://sub.domain.co.kr",
                        "http://local.sub.domain.co.kr",
                        "http://local-test.sub.domain.co.kr",
                        "sub.domain.co.kr",
                        "domain.co.kr",
                        "test.sub.domain.co.kr"
                    }
                };
        
                String[] expectedUrls = {
                    "test.com",
                    "domain.com",
                    "domain.co.kr"
                };
        
                // when
                // then
                for (int domainIndex = 0; domainIndex < domainUrls.length; domainIndex++) {
                    for (String url : domainUrls[domainIndex]) {
                        String convertedUrl = DomainUrlUtils.getDomainName(url);
        
                        if (expectedUrls[domainIndex].equals(convertedUrl)) {
                            System.out.println(url + " -> " + convertedUrl);
                        } else {
                            Assert.fail("origin Url: " + url + " / converted Url: " + convertedUrl);
                        }
                    }
                }
            }
        }
        

        结果:

        test.com -> test.com
        sub1.test.com -> test.com
        sub1.sub2.test.com -> test.com
        https://sub1.test.com -> test.com
        http://sub1.sub2.test.com -> test.com
        https://domain.com -> domain.com
        https://sub.domain.com -> domain.com
        http://domain.co.kr -> domain.co.kr
        http://sub.domain.co.kr -> domain.co.kr
        http://local.sub.domain.co.kr -> domain.co.kr
        http://local-test.sub.domain.co.kr -> domain.co.kr
        sub.domain.co.kr -> domain.co.kr
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-05-04
          • 2018-09-06
          • 2018-03-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多