2016-11-25 85 views
0

表达我在我的正则表达式得到正确钦点为ipv4地址,但它不工作ipv6地址在同一个ITCL文件。定期对IPv6地址

我有我的表达:

REGEXP [^:]+://[^:/]+(:[0-9]+)?/? 

这都是正确的东西,如:

https://10.77.56.89 

但同样我想要做这样的事情:

https://[2001:1:1:43::115]/ucmuser这显示不正确的格式。

回答

1

的问题是,你的正则表达式不占IPv6的数字地址(不,我会建议他们使用摆在首位,这是明智的使用DNS来将它们绑定到在生产中使用的名称)。

要检查的事情是如何失败的,让我们适应RE稍微捕捉到更多一点:

([^:]+)://([^:/]+)(:[0-9]+)?(/?) 

在这个版本中,所有未完全固定的被捕获。现在我们用regexp -inline-inline选项使regexp选项返回匹配的子字符串,即很好用于调试RE)来测试它,并且它真的有助于将RE放置在变量中并像下面那样使用它,因为它使得它更容易避免错别字):

% set RE {([^:]+)://([^:/]+)(:[0-9]+)?(/?)} 
([^:]+)://([^:/]+)(:[0-9]+)?(/?) 
% regexp -inline $RE {https://10.77.56.89} 
https://10.77.56.89 https 10.77.56.89 {} {} 
% regexp -inline $RE {https://[2001:1:1:43::115]/ucmuser} 
{https://[2001:1} https {[2001} :1 {} 

我们看到[^:]+部分是问题,因为它是在IPv6地址的第一个冒号停止。当主机名的第一部分以[开始时,我们需要添加一个特例;我们不会做全面验证(检查ip包Tcllib如果你想要的),但我们可以通过检查括号中的内容是十六进制数字或冒号做一些简单的东西。

% set RE {([^:]+)://([^]:[/]+|\[[0-9a-f:A-F]+\])(:[0-9]+)?(/?)} 
([^:]+)://([^]:[/]+|\[[0-9a-f:A-F]+\])(:[0-9]+)?(/?) 
% regexp -inline $RE {https://10.77.56.89} 
https://10.77.56.89 https 10.77.56.89 {} {} 
% regexp -inline $RE {https://[2001:1:1:43::115]/ucmuser} 
{https://[2001:1:1:43::115]/} https {[2001:1:1:43::115]} {}/

这看起来我的权利(是的,它花了一些修修补补,以获得与语法POSIX RE字符类的语法,因为相互作用的右侧)。转换为有你原来具有相同的捕获组,你的RE应该是这样的:

[^:]+://(?:[^]:[/]+|\[[0-9a-f:A-F]+\])(:[0-9]+)?/? 

(注:我们使用非捕获括号,(?: ...... ),在这个因为我们需要轮换,| ,两个子的RE之间)

+1

我是POSIX字符类的粉丝:我们可以更换'[0-9A-F :AF]'用'[[:xdigit:]:]来表示“十六进制数字或冒号” –

0

一个更宽松的变体。

% package require ip 
1.3 
% set addr1 https://10.77.56.89 
https://10.77.56.89 
% set addr2 {https://[2001:1:1:43::115]/ucmuser} 
https://[2001:1:1:43::115]/ucmuser 

刚拿到从地址的IP号码最简单的方式*:

% set ip1 [regexp -inline {\d.*\d} $addr1] 
10.77.56.89 
% set ip2 [regexp -inline {\d.*\d} $addr2] 
2001:1:1:43::115 

然后对其进行验证:

% ::ip::version $ip1 
4 
% ::ip::version $ip2 
6 

*)此方法仅用于说明目的,肯定不会对所有URL工作。原则是从一个非常简单的提取方法开始,如果有效的ip号码被严重提取并被拒绝,逐步细化该方法,直到它只是复杂的,因为它不需要。

E.g.如果我们得到这样一个URL:

set addr3 http://127.0.0.1/a/b/c/1 

上述方法将匹配到了最后一位。但是,通过稍微提炼就很容易解决:

% set ip3 [regexp -inline {\d[^/]*\d} $addr3] 
127.0.0.1 

等等。

这并不一定是一个regexp操作之一:

set ipX [string trim [lindex [split $addrX /] 2] \[]] 

作品在这里提到的所有URL。

文档: ip (package)lindexpackagesetsplitstringregexp

+0

,如果你将数字进一步放到网址上,这当然会导致你的悲伤:'http://127.0.0.1/a/ b/c/1' –

+0

@glennjackman:我不会说悲伤。这场比赛陷入了验证步骤,我将被迫花费一两分钟的时间来完善RE。使用最简单的可能的提取方法(工作),然后使用现有的实用程序进行验证总是比安排提取*和*验证的通用RE更安全和更少的工作。 –

+0

因为网址_never_在路径部分有数字... –