PHP regexp: примеры регулярных выражений. PHP (регулярное выражение) - что это такое? Примеры и проверка регулярных выражений Php preg match цифры
Регулярные выражения — очень полезный инструмент для разработчиков. Регулярные выражения позволяют проверять правильность текста, искать и изменять его.
В этой статье собраны некоторые очень полезные выражения, с которыми часто приходится работать.
Введение в регулярные выражения
При первом знакомстве с регулярными выражениями может показаться, что их сложно понять и применять. На самом деле все проще, чем кажется. Перед тем как приступить к рассмотрению сложных примеров, разберем основы:
Функции для работы с регулярными выражениями в PHP
Проверка домена
Проверка на правильное доменное имя.
$url = "http://example.com/"; if (preg_match("/^(http|https|ftp)://(*(?:.*)+):?(d+)?/?/i", $url)) { echo "Ok."; } else { echo "Wrong url."; }
Подсветка слов в тексте
Очень полезное регулярное выражение для . Пригодится для поиска.
$text = "Sample sentence, regex has become popular in web programming. Now we learn regex. According to wikipedia, Regular expressions (abbreviated as regex or regexp, with plural forms regexes, regexps, or regexen) are written in a formal language that can be interpreted by a regular expression processor"; $text = preg_replace("/b(regex)b/i", "1", $text); echo $text;
Подсветка результатов поиска в WordPress
Как уже было сказано, предыдущий пример очень полезен при . Применим его к WordPress. Откройте файл search.php, найдите функцию the_title(). Замените её следующим:
Echo $title;
Теперь, перед этой строкой вставьте код:
\0", $title); ?>
Откройте файл style.css . Добавьте в него строку:
Strong.search-excerpt { background: yellow; }
Получить все изображения из HTML документа
Если вам когда-нибудь понадобиться найти все изображения на HTML странице, вам пригодится следующий код. С его помощью можно легко создать загрузчик изображений, используя .
$images = array(); preg_match_all("/(img|src)=("|")[^"">]+/i", $data, $media); unset($data); $data=preg_replace("/(img|src)("|"|="|=")(.*)/i","$3",$media); foreach($data as $url) { $info = pathinfo($url); if (isset($info["extension"])) { if (($info["extension"] == "jpg") || ($info["extension"] == "jpeg") || ($info["extension"] == "gif") || ($info["extension"] == "png")) array_push($images, $url); } }
Удаление повторяющихся слов (не зависимо от регистра)
$text = preg_replace("/s(w+s)1/i", "$1", $text);Удаление повторяющихся знаков препинания
Похоже на предыдущее, только удаляет знаки препинания.
$text = preg_replace("/.+/i", ".", $text);
Нахождение XML/HTML тега
Простая функция, которая принимает два аргумента: тег, который необходимо найти, и строка, содержащая XML или HTML.
Function get_tag($tag, $xml) { $tag = preg_quote($tag); preg_match_all("{<".$tag."[^>]*>(.*?)".$tag.">."}", $xml, $matches, PREG_PATTERN_ORDER); return $matches;
Нахождение XML/HTML тега с определенным значением атрибута
Функция похожа на предыдущую, но появляется возможность указать атрибут тега. Например: Function get_tag($attr, $value, $xml, $tag=null) {
if(is_null($tag))
$tag = "\w+";
else
$tag = preg_quote($tag);
$attr = preg_quote($attr);
$value = preg_quote($value);
$tag_regex = "/<(".$tag.")[^>]*$attr\s*=\s*".
"(["\"])$value\\2[^>]*>(.*?)<\/\\1>/"
preg_match_all($tag_regex,
$xml,
$matches,
PREG_PATTERN_ORDER);
return $matches;
}
Функция позволяет находить или проверять правильность шестнадцатеричных кодов цвета.
$string = "#555555";
if (preg_match("/^#(?:(?:{3}){1,2})$/i", $string)) {
echo "example 6 successful.";
}
Данный код найдет и выведет на экран текст между тегами
$fp = fopen("http://www.catswhocode.com/blog","r");
while (!feof($fp)){
$page .= fgets($fp, 4096);
}
$titre = eregi(" Многие сайты работают на веб-сервере Apache. Если ваш сайт тоже работает на тако сервере, то следующие регулярки могут пригодиться.
//Logs: Apache web server
// Успешные доступы к html файлам. Полезно для подсчета показов страниц.
"^((?#client IP or domain name)S+)s+((?#basic authentication)S+s+S+)s+[((?#date and time)[^]]+)]s+"(?:GET|POST|HEAD) ((?#file)/[^ ?"]+?.html?)??((?#parameters)[^ ?"]+)? HTTP/+"s+(?#status code)200s+((?#bytes transferred)[-0-9]+)s+"((?#referrer)[^"]*)"s+"((?#user agent)[^"]*)"$"
//Logs: Apache web server
//404 ошибки
"^((?#client IP or domain name)S+)s+((?#basic authentication)S+s+S+)s+[((?#date and time)[^]]+)]s+"(?:GET|POST|HEAD) ((?#file)[^ ?"]+)??((?#parameters)[^ ?"]+)? HTTP/+"s+(?#status code)404s+((?#bytes transferred)[-0-9]+)s+"((?#referrer)[^"]*)"s+"((?#user agent)[^"]*)"$"
}
Это регулярное выражение проверяет строку по пунктам: строка должна содержать не менее 6 букв, цифр, подчеркиваний и тире. Строка должна содержать хотя бы одну заглавную букву, строчную и цифру.
"A(?=[-_a-zA-Z0-9]*?)(?=[-_a-zA-Z0-9]*?)(?=[-_a-zA-Z0-9]*?)[-_a-zA-Z0-9]{6,}z"
Если вы используете WordPress вам может пригодиться функция, которая получит все изображения из поста и покажет их. Для использования данного кода, скопируйте его в файлы своей темы.
post_content;
$szSearchPattern = "~]* />~";
// Run preg_match_all to grab all the images and save the results in $aPics
preg_match_all($szSearchPattern, $szPostContent, $aPics);
// Check to see if we have at least 1 image
$iNumberOfPics = count($aPics);
if ($iNumberOfPics > 0) {
// Now here you would do whatever you need to do with the images
// For this example the images are just displayed
for ($i=0; $i < $iNumberOfPics ; $i++) {
echo $aPics[$i];
};
};
endwhile;
endif;
?>
Эта функция также есть в WordPress, она позволяет автоматически заменить текстовые смайлы на картинки.
$texte="A text with a smiley:-)";
echo str_replace(":-)","",$texte);
Чаще всего регулярные выражения используются в Perl в операторах поиска и замены, таких как s//
, m/
, операторах связки =~
или !=
и т.д. Как правило все эти операторы имеют схожие опции такие как: Обычно все эти опции обозначают как "/x". Их можно использовать даже внутри шаблонов, используя новую конструкцию (?...) Регулярные выражения или шаблоны (pattern) то же самое, что и regexp процедуры в Unix. Выражения и синтаксис заимствованы из свободно распространяемых процедур V8 Генри Спенсера (Henry Spencer), там же они подробно и описаны. В шаблонах используются следующие метасимволы (символы обозначающие группы других символов) часто называемые egrep - стандартом: Метасимволы имеют модификаторы (пишутся после метасимвола): Во все других случаях фигурные скобки считаются обычными (регулярными) символами. Таким образом "*" эквивалентна {0,} , "+" - {1,} и "?" - {0,1}. n и m не могут быть больше 65536. По умолчанию действие метасимволов "жадно" (greedy). Совпадение распространяется столько раз, сколько возможно, не учитывая результат действия следующих метасимволов. Если вы хотите "уменьшить их аппетит", то используйте символ "?". Это не изменяет значение метасимволов, просто уменьшает распространение. Таким образом: Шаблоны работают так же, как и двойные кавычки, поэтому в них можно использовать `\` - символы (бэкслэш-символы): Дополнительно в Perl добавлены следующие метасимволы: Обратите внимание, что все это "один" символ. Для обозначения последовательности применяйте модификаторы. Так: Кроме того существуют мнимые метасимволы. Обозначающие не существующие символы в месте смены значения. Такие как: Граница слова (\b) - это мнимая точка между символами \w и \W. Внутри класса символов "\b" обозначает символ backspace (стирания). Метасимволы \A
и \Z
- аналогичны "^" и "$", но если начало строки "^" и конец строки "$" действуют для каждой строки в многострочной строке, то \A
и \Z
обозначают начало и конец всей многострочной строки. Если внутри шаблона применяется группировка (круглые скобки), то номер подстроки группы обозначается как "\цифра". Заметьте, что за шаблоном в пределах выражения или блока эти группы обозначаются как "$цифра". Кроме этого существуют дополнительные переменные: Пример:
$s = "Один 1 два 2 и три 3";
if ($s =~ /(\d+)\D+(\d+)/)
{
print "$1\n"; # Результат "1"
print "$2\n"; # "2"
print "$+\n"; # "2"
print "$&\n"; # "1 два 2"
print "$`\n"; # "Один "
print "$"\n"; # " и три 3"
}
Perl версии 5 содержит дополнительные конструкции шаблонов: Пример:
$s = "1+2-3*4";
if ($s =~ /(\d)(?=-)/) # Найти цифру за которой стоит "-"
{
print "$1\n"; # Результат "2"
}
else
{
print "ошибка поиска\n";
}
(?!шаблон)- "заглядывание" вперед по отрицанию: Пример:
$s = "1+2-3*4";
if ($s =~ /(\d)(?!\+)/) # Найти цифру за которой не стоит "+"
{
print "$1\n"; # Результат "2"
}
else
{
print "ошибка поиска\n";
}
(?ismx) - "внутренние" модификаторы. Удобно применять в шаблонах, где например нужно внутри шаблона указать модификатор. Правила регулярного выражения. (regex)
Регулярные выражения
(сокращенно — regex
) представляют собой последовательности символов, которые формируют шаблоны поиска. В основном они используются в шаблонах сопоставления со строками. Краткая история PHP
включает в себя три основные функции для работы с PCRE
— preg_match
, preg_match_all
и preg_replace
. Сравнение соответствия
Выражение возвращает 1
, если соответствие установлено, 0
— если нет, и false
— если возникает ошибка: int preg_match (string $pattern,
string $subject [,
array &$matches [,
int $flags = 0 [,
int $offset = 0
]]]) Регулярного выражения пример, который возвращает количество найденных совпадений: int preg_match_all (string $pattern,
string $subject [,
array &$matches [,
int $flags = PREG_PATTERN_ORDER [,
int $offset = 0
]]]) Замена
Выражение возвращает замененную строку или массив (на основе объекта $subject
): mixed preg_replace (mixed $pattern,
mixed $replacement,
mixed $subject [,
int $limit = -1 [,
int $count
]]) Регулярные выражения в JavaScript
выглядят почти так же, как и в PHP
. Сравнение соответствия
Возвращает массив совпадений или null
, если совпадений не найдено: string.match(RegExp); Замена
Регулярное выражение, которое возвращает строку с выполненными заменами: string.replace(RegExp, replacement); Рассмотрим пример, в котором нужно найти адреса электронной почты в базе кода. Наша цель: Аналоговые сокеты
Регулярные выражения состоят из двух типов символов: Представьте себе входные строки как болты, а шаблон — как набор разъемов для них (в соответствующем порядке). Специальные символы
При проверке регулярных выражений нужно знать, как работают специальные символы: Совпадение со всеми символами, кроме новых строк. Если хотите проверить на соответствие точке, и только точке — , на соответствие буквам, цифрам и нижнему подчеркиванию — w
Совпадение с символами внутри скобок. Поддерживает диапазоны. Некоторые примеры: Звездочка обозначает 0 или более символов. Соответствие 1 или более символам. Фигурные скобки {}. Минимальное и максимальное значения. Некоторые примеры синтаксиса регулярных выражений: Добавим все это, чтобы получить регулярное выражение для адресов электронной почты: /+@+(.+)*/i
preg_match_all("/+@+(.+)*/i",
$input_lines,
$output_array); Задача
: убедиться, что вводимые данные — это то, что мы ожидаем. Цель 1
: /[^w$.]/ Цель 2: /^{1,2}$/
Регулярные выражения подходят для поиска элементов, но вам нужно знать, что именно вы ищете. Многие случаи лучше обрабатывать с помощью функции PHP filter_var
. Например, проверка адреса электронной почты должна выполняться с помощью встроенных фильтров PHP
: filter_var("[email protected]",
FILTER_VALIDATE_EMAIL) Регулярные выражения в конце строки используют анкоры: ^
— указывает начало строки. if (!preg_match("%^{1,2}$%", $_POST["subscription_frequency"])) {
$isError = true;
} [^abc]
— все, кроме a
, b
или c
, включая новые строки. Пример, который обеспечивает ввод только буквенно-цифровых символов, тире, точки, подчеркивания: if (preg_match("/[^0-9a-z-_.]/i", $productCode)) {
$isError = true;
} Наиболее распространенными функциями PCRE
для выполнения поиска и замены являются preg_replace()
и preg_replace_callback()
. Но есть также preg_filter()
и preg_replace_callback_array()
, которые делают почти то же самое. Обратите внимание, что функция preg_replace_callback_array()
доступна, начиная с PHP7
. $subject = "I want to eat some apples.";
echo preg_replace("/apple|banana|orange/", "fruit", $subject); Результат
I want to eat some fruits. Если в регулярном выражении есть подшаблоны (в круглых скобках
), можно заменить $N
или N
(где N
является целым числом > = 1
), это называется «обратная ссылка». $subject = "7/11";
echo preg_replace("/(d+)/(d+)/", "$2/$1", $subject); Результат
$subject = "2001-09-11";
echo preg_replace("/(d+)-(d+)-(d+)/", "$3/$2/$1", $subject); Результат
$subject = "Please visit https://php.earth/doc for more articles.";
echo preg_replace("#(https?://([^s./]+(?:.[^s./]+)*[^s]*))#i",
"$2",
$subject); Результат
Please visit php.earth/doc for more articles. Иногда нужно выполнить сложный поиск и замену, например, при фильтрации/проверке перед заменой. В этой ситуации может пригодиться preg_replace_callback()
. Регулярные выражения – это очень полезный инструмент для разработчиков. С их помощью можно находить, определять или заменять текст, слова или любые другие символы. В сегодняшней статье собраны 15 наиболее полезных регулярных выражений, которые пригодятся любому веб-разработчику. Многим начинающим разработчикам кажется, что регулярные выражения очень сложны для понимания и использования. На самом деле, все не так уж сложно, как может показаться. Прежде чем мы непосредственно перейдем к регулярным выражениям, с их полезным и универсальным кодом, давайте взглянем на основы: Синтаксис регулярных выражений
PHP-функции для регулярных выражений
Проверяем, является ли строка правильным доменным именем
$url = "http://komunitasweb.com/";
if (preg_match("/^(http|https|ftp)://(*(?:.*)+):?(d+)?/?/i", $url)) {
echo "Your url is ok.";
} else {
echo "Wrong url.";
}
Это очень полезное регулярное выражение, с его помощью вы можете найти нужное слово и подсветить его. Особенно полезно для отображения результатов поиска.
$text = "Sample sentence from KomunitasWeb, regex has become popular in web programming. Now we learn regex. According to wikipedia, Regular expressions (abbreviated as regex or regexp, with plural forms regexes, regexps, or regexen) are written in a formal language that can be interpreted by a regular expression processor";
$text = preg_replace("/b(regex)b/i", "1", $text);
echo $text;
Как уже говорилось в предыдущем примере, этот пример кода, удобно использовать в выдаче поисковых результатов и есть отличный способ внедрить эту функцию в wordpress-блог. Откройте ваш файл search.php, и найдите функцию the_title(). Замените ее следующим кодом: Echo $title;
Теперь, выше этой строки, добавьте этот код:
\0",
$title);
?>
Сохраните файл search.php, и откройте style.css. Добавьте следующую строку: Strong.search-excerpt { background: yellow; }
Если вам когда-нибудь требовалось получить все картинки с веб-страницы, этот код должен быть Вы легко сможете создать загрузчик изображений с помощью возможностей cURL
$images = array();
preg_match_all("/(img|src)=("|\")[^"\">]+/i", $data, $media);
unset($data);
$data = preg_replace("/(img|src)("|\"|="|=\")(.*)/i", "$3", $media);
foreach ($data as $url) {
$info = pathinfo($url);
if (isset($info["extension"])) {
if (($info["extension"] == "jpg") ||
($info["extension"] == "jpeg") ||
($info["extension"] == "gif") ||
($info["extension"] == "png"))
array_push($images, $url);
}
}
Во время печатания, часто повторяются слова? Поможет это регулярное выражение.
$text = preg_replace("/s(w+s)1/i", "$1", $text);
То же самое, только для пунктуации. Попрощайтесь с двойными запятыми.
$text = preg_replace("/.+/i", ".", $text);
Эта простая функция, принимает два аргумента. Первый – это тэг, который вам нужно найти, и второй – это переменная, содержащая XML или HTML. Повторюсь, эту функцию очень удобно использовать вместе с cURL. Function get_tag($tag, $xml) {
$tag = preg_quote($tag);
preg_match_all("{<".$tag."[^>]*>(.*?)".$tag.">."}",
$xml,
$matches,
PREG_PATTERN_ORDER);
return $matches;
}
Эта функция очень похожа на предыдущую, за исключением того, что вы можете задать тегу нужный атрибут. Например, вы легко сможете найти Function get_tag($attr, $value, $xml, $tag=null) {
if(is_null($tag))
$tag = "\w+";
else
$tag = preg_quote($tag);
$attr = preg_quote($attr);
$value = preg_quote($value);
$tag_regex = "/<(".$tag.")[^>]*$attr\s*=\s*".
"(["\"])$value\\2[^>]*>(.*?)<\/\\1>/"
preg_match_all($tag_regex,
$xml,
$matches,
PREG_PATTERN_ORDER);
return $matches;
}
Еще один полезный инструмент для веб-разработчика! Он позволяет вам находить/проверять шестнадцатеричные значение цвета.
$string = "#555555";
if (preg_match("/^#(?:(?:{3}){1,2})$/i", $string)) {
echo "example 6 successful.";
}
Этот фрагмент кода найдет и выведет на экран текст, находящийся внутри тэгов
$fp = fopen("http://www.catswhocode.com/blog","r");
while (!feof($fp)){
$page .= fgets($fp, 4096);
}
$titre = eregi(" Большинство сайтов запущено на всем известном веб-сервере Apache. Если ваш сайт находится в их числе, почему бы не использовать PHP и регулярные выражения для разбора логов апача?
//Logs: Apache web server
//Successful hits to HTML files only. Useful for counting the number of page views.
"^((?#client IP or domain name)S+)s+((?#basic authentication)S+s+S+)s+[((?#date and time)[^]]+)]s+"(?:GET|POST|HEAD) ((?#file)/[^ ?"]+?.html?)??((?#parameters)[^ ?"]+)? HTTP/+"s+(?#status code)200s+((?#bytes transferred)[-0-9]+)s+"((?#referrer)[^"]*)"s+"((?#user agent)[^"]*)"$"
//Logs: Apache web server
//404 errors only
"^((?#client IP or domain name)S+)s+((?#basic authentication)S+s+S+)s+[((?#date and time)[^]]+)]s+"(?:GET|POST|HEAD) ((?#file)[^ ?"]+)??((?#parameters)[^ ?"]+)? HTTP/+"s+(?#status code)404s+((?#bytes transferred)[-0-9]+)s+"((?#referrer)[^"]*)"s+"((?#user agent)[^"]*)"$"
Если вы любитель типографики, вам понравится это регулярное выражение, заменяющее обычные двойные кавычки, на “умные кавычки”. Похожее регулярное выражение используется в wordpress в контенте страницы. Preg_replace("B"b([^"x84x93x94rn]+)b"B", "?1?", $text);
Это регулярное выражение будет следить за тем, чтобы в текстовое поле было введено не менее шести символов, цифры, дефисы и подчеркивания. Текстовое поле должно содержать как минимум один символ верхнего регистра, один нижнего регистра и одну цифру.
"A(?=[-_a-zA-Z0-9]*?)(?=[-_a-zA-Z0-9]*?)(?=[-_a-zA-Z0-9]*?)[-_a-zA-Z0-9]{6,}z"
Поскольку многие из вас являются пользователями WordPress, вам возможно пригодится код, который позволяет получить все картинки, из текста статьи, и вывести их. Для того, чтобы использовать этот код, просто вставьте его в любой файл вашей темы.
post_content;
$szSearchPattern = "~]* />~";
// Run preg_match_all to grab all the images and save the results in $aPics
preg_match_all($szSearchPattern, $szPostContent, $aPics);
// Check to see if we have at least 1 image
$iNumberOfPics = count($aPics);
if ($iNumberOfPics > 0) {
// Now here you would do whatever you need to do with the images
// For this example the images are just displayed
for ($i=0; $i < $iNumberOfPics ; $i++) {
echo $aPics[$i];
};
};
endwhile;
endif;
?>
Другая функция, используемая в wordpress – позволяет автоматически заменять символы смайлов на картинку смайла.
$texte="A text with a smiley:-)";
echo str_replace(":-)","",$texte);
Нахождение шестнадцатеричных кодов цвета
Нахождение заголовка страницы
Парсинг логов Apache
Замена двойных кавычек на фигурные
preg_replace("B"b([^"x84x93x94rn]+)b"B", "?1?", $text);
Проверка сложности пароля
WordPress: Получение изображений поста с помощью регулярного выражения
Преобразование смайлов в картинки
\t
- символ табуляции
\n
- новая строка
\r
- перевод каретки
\а
- перевод формата
\v
- вертикальная табуляция
\a
- звонок
\e
- escape
\033
- восьмеричная запись символа
\x1A
- шестнадцатеричная
\c[
- control символ
\l
- нижний регистр следующего символа
\u
- верхний регистр -//-
\L
- все символы в нижнем регистре до \E
\U
- в верхнем -//-
\E
- ограничитель смены регистра
\Q
- отмена действия как метасимвола
1.7K
Общее использование регулярных выражений в PHP
Общее использование регулярных выражений в JavaScript
Особенности регулярных выражений в JavaScript
Принципы составления шаблонов регулярных выражений
o — соответствует любым a, b или c.
o прописные буквы.
o любая цифра.
o — соответствует любому буквенному символу в нижнем или верхнем регистре.
Опционально? Соответствие 0 или 1.
Звездочка *.
o {1,} не менее 1.
o {1,3} от 1 до 3.
o {1,64} от 1 до 64.
Как это выглядит в PHP
:
Использование регулярного выражения для валидации
Когда не стоит использовать регулярное выражение для проверки?
Валидация с помощью регулярных выражений
$
— знак доллара, который указывает конец строки.Исключенные классы символов
Поиск и замена
Заменить слова в списке
Перестановка двух чисел
Изменение форматирования даты
Простой пример замены URL-адреса в теге
Введение в регулярные выражения
Регулярное выражение
Означает
foo
Строка “foo”
^foo
Строка начинается с “foo”
foo$
Строка заканчивается на “foo”
^foo$
«foo» встречается в строке только один раз
a, b, или c
любой символ в нижнем регистре
[^A-Z]
любой символ, не находящийся в верхнем регистре
(gif|jpg)
Означает как «gif” так и “jpeg”
+
Один или более символов нижнего регистра
Любая цифра, точка или знак минус
^{1,}$
Любое слово, хотя бы одна буква, число или _
()()
wy, wz, xy, или xz
(^A-Za-z0-9)
Любой символ (не число и не буква)
({3}|{4})
Означает три буквы или 4 цифры
Функция
Описание
preg_match()
Функция preg_match() ищет строку по заданному шаблону, возвращает true, если строка находится и false, в остальных случаях
preg_match_all()
Функция preg_match_all() находит все вхождения строки, заданной по шаблону
preg_replace()
Функция preg_replace(), действует по тому же принципу, что и ereg_replace(), за исключением того, что регулярные выражения можно использовать как для задания шаблона поиска, так и для строки, на которую следует заменить, найденное значение.
preg_split()
Функция preg_split(), действует так же как split(), за исключением того, что регулярное выражение можно использовать в качестве параметра для шаблона поиска.
preg_grep()
Функция preg_grep() ищет все элементы входного массива, возвращая все элементы, соответствующие шаблону регулярного выражения.
preg_quote()
Экранирует символы регулярного выражения
Проверка доменного имени
Подсветка слова в тексте
Подсветка результатов поиска в WordPress блоге
Получение всех картинок из HTML-документа
Удаление повторяющихся слов (не чувствителен к регистру)
Удаление повторяющейся пунктуации
Поиск XML/HTML тэгов
Поиск XHTML/XML тэгов с определенным значением атрибута
Поиск шестнадцатеричных значений цветов
Поиск заголовка статьи
Парсинг логов Apache
Замена двойных кавычек “умными” кавычками
Комплексная проверка пароля
WordPress: Использование регулярного выражения для получения картинок из записи
Генерация автоматических смайлов
Рекомендуем также