有没有一个好的(最好是经过测试的)正则表达式,只接受有效的DNS主机名、IPv4或IPv6地址?
我了解您可能被迫使用正则表达式。然而,如果可能的话,最好避免使用正则表达式来完成此任务,并使用Java库类来进行验证。
如果您想一起进行验证和DNS查找,则InetAddress.getByName(String)
是一个很好的选择。它可以一次性处理DNS、IPv4和IPv6,返回一个包含DNS名称(如果提供)和IPv4或IPv6地址的整洁封装的InetAddress
实例。
如果您只想进行语法验证,则Apache commons有一些类可以完成这个任务:DomainValidator
和InetAddressValidator
。
Guava推出了一个新类HostSpecifier,它甚至可以验证主机名(如果是主机名)是否以有效的“公共后缀”结尾(例如“.com”,“.co.uk”等),这是基于最新的mozilla公共后缀列表。使用手动编写的正则表达式是不建议尝试的!
正如其他人所说,使用正则表达式实现这个功能是很具有挑战性并且不可取的。但是使用IPAddress Java库可以轻松完成,该库能够解析主机名、IPv4和IPv6地址,而不会触发DNS查找。免责声明:我是该库的项目经理。
示例代码:
check("1.2.3.4");
check("::1");
check("a.b.com");
static void check(String hostStr) {
HostName host = new HostName(hostStr);
try {
host.validate(); // triggers exception for invalid
if(host.isAddress()) {
IPAddress address = host.asAddress();
System.out.println(address.getIPVersion() + " address: " + address);
} else {
System.out.println("host name: " + host);
}
} catch(HostNameException e) {
System.out.println(e.getMessage());
}
}
输出:
IPv4 address: 1.2.3.4
IPv6 address: ::1
host name: a.b.com
public static boolean isValidHostNameSyntax(String candidateHost) {
if (candidateHost.contains("/")) {
return false;
}
try {
// WORKAROUND: add any scheme and port to make the resulting URI valid
return new URI("my://userinfo@" + candidateHost + ":80").getHost() != null;
} catch (URISyntaxException e) {
return false;
}
}
你也可以这样做。比如说:
public boolean isHostnameValid(String hostname) {
try {
InetAddress.getAllByName(hostname); // throws an error when the hostnme could not be found, if so, then return false
return true;
} catch(Exception exc) {
return false;
}
}
DomainValidator
)都有可能过时。然而,该API确实允许您提供更更新的表格;请参阅updateTLDOverride
方法。 - Stephen C