2016-11-25 134 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_在路徑部分有數字... –