Для приложения, которое я разрабатываю, мне нужен Perl-скрипт, который просматривает массивный CSV-файл и гарантирует, что каждая строка содержит действительный URI. Ранее я уже задавал вопрос о разборе файла CSV, и я начал использовать Text::CSV
, чтобы сделать мою жизнь намного проще. Теперь у меня есть проблема с гарантией, что URI действителен.
Из-за характера моего заявления URI не обязательно должны принимать полную форму
protocol://username:password@domain.extension/request?vars=values
Скорее меня интересует только часть запроса об этом. Для обычного веб-сайта это будет что-нибудь после .com
, .edu
и т. Д.
В настоящее время у меня есть следующий скрипт Perl:
if($_ !~ /^(?:[a-z0-9-._~!$&'()*+,;=:/?@]|%[0-9A-F]{2})*$/i){
print "Invalid URL format";
exit;
} else {
/* stuff */
}
Регулярное выражение должно быть довольно простым. Запрос может содержать один из небольшого набора символов ([a-z0-9-._~!$&'()*+,;=:/?@]
) или может содержать знак процента (%
), за которым следуют две шестнадцатеричные цифры. Любой из этих шаблонов может повторяться бесконечно.
Когда я запускаю этот скрипт, я получаю следующую ошибку:
Number found where operator expected at ./301rules.pl line 58, near "%[0"
(Missing operator before 0?)
Bareword found where operator expected at ./301rules.pl line 58, near "9A"
(Missing operator before A?)
Bareword found where operator expected at ./301rules.pl line 58, near "$/i"
(Missing operator before i?)
syntax error at ./301rules.pl line 58, near "%[0"
Совершенно очевидно, что что-то в моем регулярном выражении нужно экранировать, однако я не уверен в чем. Я попытался экранировать каждый возможный символ, чтобы создать следующее регулярное выражение:
if($_ !~ /^(?:[a-z0-9\-\.\_\~\!\$\&\'\(\)\*\+\,\;\=\:\/\?\@]|%[0-9A-F]{2})*$/i){
Однако, когда я сделал это, он просто позволил каждой строке пройти тест, даже строки, которые, как я знал, являются недействительными, такие как te%st
или é
Так кто-нибудь имеет опыт работы с Perl regex и знает, что мне нужно убежать, а что мне не следует убегать? С 19 различными символами мне не хочется пробовать все 2 ^ 19 = 524288 возможностей.
РЕДАКТИРОВАТЬ - голосование закрыть. Я обнаружил, что проблема действительно существовала непосредственно над этим циклом, хотя я еще не совсем понимаю, почему.
У меня было:
if( $_ == "" ){
next;
}
/* regex conditional from above */
По какой-то причине он продолжал оценивать как true и переходить к следующей итерации, несмотря на то, что в $_
явно хранятся данные. Я выясню, почему это так, но сейчас регулярное выражение работает нормально, когда все вышло.