forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   PHP / MySQL (http://forum.boolean.name/forumdisplay.php?f=135)
-   -   Готовим регулярные выражения: Проверка строки по шаблону (http://forum.boolean.name/showthread.php?t=15774)

Randomize 04.11.2011 23:23

Готовим регулярные выражения: Проверка строки по шаблону
 
Вечер добрый, мои дорогие пекари.
Сегодня я решил окунуть вас с головой в такую часто вызывающую у многих головную боль тему как "Регулярные выражения".
Кто не в курсе эта такой особый способ работы с текстом. И применений ему масса. И эту массу для наполнения ваших булочек мы сегодня будем разбирать по составу :B

Сегодня мы будем проверять строку по шаблону.

Вам понадобится:
Онлайн тестер регулярных выражений
http://www.functions-online.com/preg_match.html
Как юзать под оффтопом:

subject - наш вводимый текст
pattern - наше выражение
flags и offset пока не трогаем.

В результате выполнения нас пока что интересует только result.
Он булевой:
1 - строка валидна
0 - строка не валидна


Или использовать вот такое на своём веб сервере:
PHP код:

<?
$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) Лимит на количество цифр в порте.


Спасибо вам за уделённое время и удачных экспериментов. Если дело пойдёт - будет вам вторая часть.

ABTOMAT 04.11.2011 23:56

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Я всё понял! Хороший урок.
Look at my horse, my horse is amazing!

baton4ik 04.11.2011 23:57

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Легко читаемая и понятная мини-статья, спасибо.

Цитата:

私の馬を見て、私の馬は素晴らしいです!
http://www.youtube.com/watch?v=_RjMSWhGWak


Цитата:

PHP код:

/^http(s?)://$/ 

Далее домен: Буквы от a-z цифры 0-9, тире и точка и их в общей сложности может быть сколько угодно.
[a-z0-9-.]+
Тут, очевидно, имелось в виду /^http(s?):\/\/$/ ?

Randomize 05.11.2011 00:06

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Цитата:

Сообщение от baton4ik (Сообщение 208406)
Легко читаемая и понятная мини-статья, спасибо.
Тут, очевидно, имелось в виду /^http(s?):\/\/ ?

Ой! Булочный тег [ php] навёл марафет.

VotapilD 05.11.2011 15:26

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Наконец-то я увидел правильный порядок разбора *_* Спасибо, а то. когда нужно было - путался постоянно =(
Лошадь и вправду прекрасна %)

Randomize 06.11.2011 00:33

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Принимаются предложения тем для следующей статейки.

moka 06.11.2011 00:42

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
JSON

.Squid 06.11.2011 00:50

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Цитата:

Сообщение от MoKa (Сообщение 208522)
JSON

Я, честно говоря, не знаю, что о нем можно написать. Вроде как очень простой формат (не путать с "не функциональный") - из Википедии можно все понять.
Но если будет хорошая статья, то я за.

moka 06.11.2011 01:30

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Многие не совсем понимают его плюсов. И используют частенько совсем не по назначению.

Если статью направить на описание плюсов в использовании например с точки зрения скорости разработки, и удобства, используя серверную часть на PHP или даже собственный (WebSockets протокола), то статья имеет потенциал.

Сейчас сильно развивается направление WebSockets, а как мы знаем, юзается JavaScript, и JSON в данном случае - готовое решение для сериализации.
Рассмотрение этого формата с этой точки зрения, потенциально.

Формат простой, и для тех кто смышлённый, статьи не нужны. А те кто читает статьи, нуждается в разъяснениях, это отличный момент, когда можно качественно "промыть" и направить мышление у начинающих..

.Squid 06.11.2011 02:12

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Ну тогда я бы на месте автора привел несколько примеров использования вне веб-разработки. Для геймдева этот формат имхо лучше, чем XML. И не только для хранения конфигураций, но и даже для текстовых форматов медии. Ребята из bitsquid его нахваливают.

moka 06.11.2011 02:16

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Есть даже NoSQL базы данных, построенные на подобных структурах: ключ : значение, а не таблицах..

ABTOMAT 27.06.2012 05:17

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Только что эта статья спасла мою жопу на работе.
Ещё раз респект!

Trazzy 14.03.2013 19:34

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Есть такое выражение:
^([0-9а-z]+)$

использую в htaccess таким образом:
RewriteEngine On
RewriteRule ^([0-9а-z]+)$ page.php?go=$1 [L]

в общем все, что совпадает с этим выражением передается в виде GET-запроса странице pаge.php

Вопрос: как сделать обратную этому функцию? То есть чтобы все остальное попадало на другую страницу.

З.Ы. я так понял в регулярках нет такой вещи как NOT или я ошибаюсь?

Randomize 14.03.2013 20:22

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
Цитата:

Сообщение от 2Fake (Сообщение 254896)
Есть такое выражение:
^([0-9а-z]+)$

использую в htaccess таким образом:
RewriteEngine On
RewriteRule ^([0-9а-z]+)$ page.php?go=$1 [L]

в общем все, что совпадает с этим выражением передается в виде GET-запроса странице pаge.php

Вопрос: как сделать обратную этому функцию? То есть чтобы все остальное попадало на другую страницу.

З.Ы. я так понял в регулярках нет такой вещи как NOT или я ошибаюсь?

Используй отрицания:
RewriteRule ^([^0-9^a-z]+)$ other.php?go=$1 [L]

^0-9 - не цифры
^a-z - не буквы
^sosiska - не сосиска

Trazzy 14.03.2013 21:59

Ответ: Готовим регулярные выражения: Проверка строки по шаблону
 
То что надо.
Thnx! (особенно за сосиску) :)


Часовой пояс GMT +4, время: 23:16.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot