2012-04-24 1 views
1

Я использую регулярное выражение для проверки URL. Это выражение очень хорошо работает в JavaScript, но в PHP это дает мне эту ошибкурегулярное выражение для проверки правильности URL-адреса в PHP

A PHP Error was encountered 

Severity: Warning 

Message: preg_match() [function.preg-match]: Unknown modifier '(' 

Filename: home/auth.php 

Line Number: 1596 
A PHP Error was encountered 

Severity: Warning 

Message: preg_match() [function.preg-match]: Unknown modifier '(' 

Filename: home/auth.php 

Line Number: 1601 

Это мое выражение

$pattern ="/^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*(\.){1}((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/"; 

Это функция PHP

public function valid_url($data) 
{ 
    $data = trim($data); 

    if(!$data) 
    { 
     return TRUE;    
    } 

    $pattern ="/^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*(\.){1}((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/"; 
    $valid = preg_match($pattern,$data); 

    if(!$valid) 
    { 
     $data = "http://".$data; 
     $valid = preg_match($pattern,$data); 
    } 

    if(!$valid) 
    { 
     $this->form_validation->set_message('valid_url', 'Please enter a valid URL.'); 
     return FALSE;   
    } 
    else 
    { 
     return TRUE; 
    }  
} 

Я не очень хорошо в регулярных выражениях, поэтому я не мог понять проблему, пожалуйста, помогите мне исправить регулярное выражение.

ответ

6

Ничего себе, это большое выражение. Я обнаружил в нем несколько недостатков, и, надеюсь, объясню их вам. Разделите его отдельно:

$pattern ="/ 

Это была ваша первая ошибка. Поскольку косая черта используется в нескольких разделах URL-адреса, вы должны использовать другой разделитель. Я бы предложил тильду ~, так как это часто не используется в URL-адресе. Это означало бы, что вам не нужно будет избегать косой черты каждый раз с \/.

^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+ 

Этот класс символов содержит следующую ошибку. В пределах символьного класса точка просто означает точку. Нет необходимости избегать этого. Кроме того, при размещении тире в конце, он также не нуждается в экранировании, поскольку это не может означать диапазон. Класс персонажа может быть сокращен до [a-zA-Z0-9.-]+.

(\:[a-zA-Z0-9\.&%\$\-]+ 

Здесь мы имеем следующую ошибку, & внутри класса символов. Это будет соответствовать & или a или m или a;, а не только &. Вам не нужно преобразовывать его в html-код, так как это означает, что он соответствует любому из символов, содержащихся в коде. И используя предыдущие знания, вам не нужно избегать точки или тире, если она находится в конце. Вам также не нужно скрывать знак доллара, так как в классе персонажей это означает только доллар.Помните, что в классе символов все метасимволы - это только стандартные символы, кроме каретки ^, обратная косая черта \, закрывающая квадратная скобка ], штрих - (но это может быть оставлено, если оно находится в конце) и все, что вы выберете как ваш разделитель, например тильда ~. Тогда этот класс символов может стать, [a-zA-Z0-9.&%$-]+.

)*@)*(\.){1} 

Отчасти это может быть ошибка, возможно, это не так. В принципе, есть ли необходимость захватить точку здесь? Если нет необходимости его захватывать, оставьте скобки в покое. Однако в повторении есть определенная ошибка. {1} полностью и совершенно излишне. Все, что нужно сделать, должно повторяться хотя бы один раз. Это просто делает код грязным. Вышеуказанное может быть сокращено до )*@)*\..

((25[0-5]|2[0-4][0-9]|[0-1]{1} 

Опять же, {1} не требуется. Удалите его, ((25[0-5]|2[0-4][0-9]|[0-1].

[0-9]{2}|[1-9]{1}[0-9]{1} 

И снова дважды, это становится [0-9]{2}|[1-9][0-9].
Вы продолжаете делать это, следующий блок кода, у вас есть, может быть сокращено:

|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9]) 

В

|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9]) 

Это не удивительно лучше, но каждый мало помогает. Далее:

|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+ 

два класса символов могут быть оптимизированы, |([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+.

\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}) 

Это очень ограничительным, но я предполагаю, что у вас есть, как это по причине, так что я оставлю его.

)(\:[0-9]+)*(/ 

А вот причина вашей ошибки. Вы не избежали косой черты. Тем не менее, я собираюсь оставить его, поскольку использование другого разделителя позволит избежать этого, а также убрать ваш шаблон.

($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/"; 

Этот класс персонажей может быть значительно сокращен, зная, что нам не нужно избегать всего внутри них. Это может стать, ($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/";.

Используя все, что мы теперь знаем, ваш рисунок можно сделать намного красивее и удобнее в обращении.

Это может стать вместо этого:

$pattern = "~^(http|https|ftp)://www\.([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])|([a-zA-Z0-9-]+\.)+(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(/($|[a-zA-Z0-9.,?'\\+&%$#=\~_-]+))*$~"; 

Теперь, когда у вас есть меньшее выражение, находя ошибки и более настройки должны быть немного легче.

Только быстрое примечание
я продолжаю замечать, что вы использовали следующий синтаксис в начале некоторых группировок, (\:. Я удалил обратную косую черту, поскольку она не нужна для двоеточия.Однако, вы пытались сделать так, чтобы группа не была захвачена? Если это так, синтаксис для этого - (?:.

Edit :: Вы также можете оптимизировать шаблон далее путем использования символьных классов

\ д = [0-9]
\ ш = [A-Za-z0-9_]

Добавление i в конец последнего разделителя шаблонов также приводит к нечувствительности к регистру. Это означает, что вместо того, чтобы писать [a-zA-Z], вы можете просто написать [a-z].

Кроме того, http|https может просто стать https?

Таким образом, вы шаблон может быть сокращен далее также:

$pattern = "~^(https?|ftp)://www\.([a-z\d.-]+(:[a-z\d.&%$-]+)*@)*((25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|[1-9])\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|[1-9]|0)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|[1-9]|0)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|\d)|([a-z\d-]+\.)+(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-z]{2}))(:\d+)*(/($|[\w.,?'\\+&%$#=\~-]+))*$~i"; 
+0

большое спасибо для ответа, но он дает ошибку снова PHP ошибка была обнаружена Серьезность: Предупреждение Сообщение: preg_match() [function.preg-матчевую]. Неизвестный модификатор '-' Имя файла: Главная/auth.php Номер строки: 1598 –

+1

Ах, моя ошибка, я не заметил тильду '~' в классе символов в конце. Она должна быть экранирована. Я отредактировал ответ, чтобы исправить это. – joe92

+0

Ошибка PHP Серьезность: предупреждение: preg_match() [ function.preg-match]: Неизвестный модификатор '\' :(:(:( –

0

Почему бы не использовать стандартную функцию php filter_var?

http://lv.php.net/manual/ru/function.filter-var.php

+0

имеет некоторые пользовательские правила Validations. так что я должен написать мне свой собственный –

1

Я вижу одну ошибку:

[0-9]+)*(/($

к

[0-9]+)*(\/($

или к

[0-9]+)*(($

Если предполагается, что / является сторонником, которым это не должно быть.

А если серьезно, разве нет другого способа добиться этого? Эта строка очень трудно устранить.

+0

танк вы очень много, я проверяю это –

+0

hmm, делая это, ошибка ушла, но действительный URL-адрес, например www.google.com, считается недействительным :( –

Смежные вопросы