2016-11-25 5 views
0

У меня есть один файл itcl, где мое регулярное выражение правильно выбрано для адреса ipv4, но то же самое оно не работает для адреса ipv6.Регулярное выражение для адреса 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 возвращает подстроки, соответствующие отличным для отладки REs, и это действительно помогает помещать 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 должен быть таким:

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

(NB: Мы используем, не захватывая скобку, (?: ... ), в этом, потому что нам нужно чередование, | между двумя суб-УЭ)

+1

Я фанат символьных классов POSIX: мы можем заменить '[0-9a-е : 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), lindex, package, set, split, string, regexp

+0

, что, конечно же, вызовет у вас горе, если вы получите цифры ниже URL:' http://127.0.0.1/a/ b/c/1' –

+0

@glennjackman: Я бы не сказал горе. Этот матч попадает на этап проверки, и я буду вынужден потратить минуту или две, уточняя RE. Используя простейший возможный метод извлечения (который работает), а затем используя существующую утилиту для проверки, всегда будет более безопасным и менее трудоемким, чем придумывание общего RE, который извлекает * и * проверяет. –

+0

Поскольку URL-адреса _never_ имеют цифры в части пути ... –