Вечер добрый, мои дорогие пекари.
Сегодня я решил окунуть вас с головой в такую часто вызывающую у многих головную боль тему как "Регулярные выражения".
Кто не в курсе эта такой особый способ работы с текстом. И применений ему масса. И эту массу для наполнения ваших булочек мы сегодня будем разбирать по составу :B
Сегодня мы будем проверять строку по шаблону.
Вам понадобится:
Онлайн тестер регулярных выражений
http://www.functions-online.com/preg_match.html
Как юзать под оффтопом:
subject - наш вводимый текст
pattern - наше выражение
flags и offset пока не трогаем.
В результате выполнения нас пока что интересует только result.
Он булевой:
1 - строка валидна
0 - строка не валидна
Или использовать вот такое на своём веб сервере:
<?
$pattern = (isset($_POST['pattern'])) ? $_POST['pattern'] : '';
$subject = (isset($_POST['subject'])) ? $_POST['subject'] : '';
$pattern = stripslashes($pattern);
$subject = stripslashes($subject);
?>
<hr />
<form action ="" method="post">
Pattern:
<input style="width: 370px; padding: 5px;" name="pattern" type="text" value="<?= $pattern; ?>" /><br />
Subject:
<textarea style="width: 370px; padding: 5px;" cols="20" rows="10" name="subject"><?= $subject; ?></textarea>
<input type="submit" value="Выполнить" />
</form>
<?= (@preg_match($pattern, $subject)) ? 'Да' : 'Неа'; ?>
И так - без вступительных речей.
Начнём по мужски сразу в лоб:
/^http(s?):\/\/[a-z0-9-.]+(:[0-9]+)?(\/(.*))?$/i
Да это же похоже на:
私の馬を見て、私の馬は素晴らしいです!
Первое, что бросается в глаза это http. Угу, значит речь идёт об
URL.
Для начала давайте подумаем из чего же состоит URL и каких видов они бывают.
* Нас на данный момент интересуют только http.
Стандартный вид:
http://domain.tld/dir/script.ext
Тоже самое но с добавлением защищённого(http) соединения:
https://domain.tld/dir/script.ext
Так же в URL может быть указан порт вот таким образом:
https://domain.tld:7777/dir/script.ext
Давайте пометим части цветами:
https://domain.tld:7777/dir/script.ext
И легенда.
¦ - префикс "s" для зашифрованного соединения (не обязателен)
¦ - доменное имя
¦ - порт (не обязателен)
¦ - путь после домена (не обязателен)
Ну что, господа, уже представили себе как это реализовывать на всяких такм strpos substr и тд? Сложно, да? А на регулярках это займёт 1 строку.
Давайте продумаем алгоритм.
1) Проверка есть ли в начале http если нет, то стоп.
2) Существует ли приставка "s" к http? Есть - оставляем, нет - фиг с ним едем дальше.
3) Введён ли домен используя сиволы a-z 0-9 точка и дефиз(русские домены пока не берём) есть? идём дальше - иначе стоп.
4) Введён ли порт? Начинается с ":" и далее только цифры 0-9 и их сколько угодно (на самом деле нет, но мы же только начинаем).
5) Есть "/"? Если да то пофигу и если нет тоже :D Но проверить надо дабы понять где кончается домен а где там начинается путь.
Теперь к делу - собираем регулярку!
Стройка начинается с сортира, а регулярка с границ выражения.
Сообщение от Регулярочка
/^...$/
|
/ - управляющий символ. Им обрамляется всё выражение целиком.
^ - старт строки.
$ - конец строки.
Дальше прямым текстом пишем что в начале строки должен быть http:
Сообщение от Регулярочка
/^http$/
|
Через такое выражение пройдёт только фраза "http".
Общие понятия по под-выражениям и диапазонам/наборам символов:
[...] - диапазон или набор символов.
Например:
[a-z] - 1 символ, который может принимать значения от a до z
[0-9] - 1 символ, который может принимать значения от 0 до 9
[0-9a-z] - 1 символ, который может принимать значения от 0 до 9 или от a до z
[0-9a-zA-Z] - 1 символ, либо любая буква англ. алфавита либо любая 1 цифра
[ab12] - 1 символ, который может принимать значения a,b,1,2 но никакие другие
Диапазон в развёрнутом виде и с 1 вариантом пишется без скобок, хотя никто не запрещает писать в скобках например так:
[a][s][s]
Для указания любого произвольного символа используется точка "."
Это делается так "[.]" или проще так "."
Например:
[.о.о.] под него подпадут слова "с
ол
од", "м
ол
од"
Так же мы можем указывать для таких диапазонов количество вхождений:
[а] - 1 буква "а"
[а]+ - 1 и более буква "a"
[a]* - сколько угодно "а" и нисколько тоже
[а]{3} - 3 буквы "а"
[а]{3,} - 3 и более букв "а"
[а]{1, 12} - от 1 до 12 букв "а"
Получается, что:
[a]* эквивалентен [a]{0,}
[a]+ эквивалентен [a]{1,}
[a]? эквивалентен [a]{0,1}
() - подвыражение. Нужно для группирования наборов символов внутри основного выражения.
Например:
([a-z][A-Z][0-9]) - говорит о том что тут 3 символа буква в нижнем регистре, буква в верхнем, цифра
Так же такие подвыражения будут возвращены в результат ф-ции ($matches)
Флаги для выражений или диапазонов (ставить после):
+ - выражение может повторяться от 1 до скольки угодно раз
? - это выражение может отсутствовать (т.е. если нет такого вхождения то нет)
{число} - это выражение повторяется указаное число раз. Так же можно указать диапазон например {2-3}
* - это выражение повторяется сколько угодно раз и может не быть вовсе
Теперь добавим первое условие - наличие "s"
(..)-подвыражение
? - флаг внутри выражения, говорящий о том что соблюдение не обязательно
Сообщение от Регулярочка
/^http(s?)$/
|
Тут уже пройдёт "http" и "https".
Теперь нам надо добавить "://" если c ":" всё в порядке, то с символом / уже нет - он управляющий! Его надо экранировать.
Это делается так: "\/\/" что равнозначно: "//"
Сообщение от Регулярочка
/^http(s?):\/\/$/
|
Далее домен: Буквы от a-z цифры 0-9, тире и точка и их в общей сложности может быть сколько угодно.
[a-z0-9-.]+
Сообщение от Регулярочка
/^http(s?):\/\/[a-z0-9-.]+$/
|
Символ плюса на конце диапазона говорит что выражение может повторяться от 1 до скольки угодно раз.
Теперь ссылки вида:
http://boolean.name
https://boolean.name
https://boo.le-an.na-me
Пройдут проверки. Слеш на конце, кстати, обломает проверку ведь его нигде не ждут :B
Теперь порт. В начала уже знакомый нам ":" потом некоторое кол-во цифр:
(:[0-9]+)?
Разберём скобку.
( - начало подвыражения
: - нужный для порта символ двоеточия
[0-9] - этот диапазон символов, в данном случае нас интересуют только цифры
+ - Указывает количество вхождений - сколько угодно раз, но не меньше 1го символа
) - конец подвыражения
? - это подвыражение не обязательно
Сообщение от Регулярочка
/^http(s?):\/\/[a-z0-9-.]+(:[0-9]+)?$/
|
Отлично! Теперь у нас спокойно пролезают:
https://domain.tld:8080
http://dom-ain.tld
https://domain.gov.ua.tld:113
Теперь завершающий этап - всё что после слеша:
(
\/ - наш заветный слеш
(.*) - всё что угодно (даже ничего) и сколько угодно
)? - всё подвыражение не обязательно
Сообщение от Регулярочка
/^http(s?):\/\/[a-z0-9-.]+(:[0-9]+)?(\/(.*))?$/
|
Теперь через наше выражение пройдёт уже почти любой url:
http://domain.tld/newthread.php?do=postthread
https://domain.tld/newthread.php?do=postthread
http://domain.tld:80/newthread.php?do=postthread
Осталось пофиксить последний изъян. Наше выражение чувствительно к регистру. Это легко исправить добавив в самый конец глобальный флажок i.
Вот так:
Сообщение от Регулярочка
/^http(s?):\/\/[a-z0-9-.]+(:[0-9]+)?(\/(.*))?$/i
|
Вот и всё.
Чего не хватает:
1) Проверки что в домене есть хотя бы одна буква кроме точки или тире
2) Лимит на количество цифр в порте.
Спасибо вам за уделённое время и удачных экспериментов. Если дело пойдёт - будет вам вторая часть.