Сышышь ты, выходи сюда,
поговорим !

Примеры регулярных выражений на PHP

Опубликовано: 24.08.2018

видео Примеры регулярных выражений на PHP

Регулярные Выражения. Основы / Regular Expressions / RegEx / RegExp

Опубликовано 9 Август, 2017



Добрый день. Устраивался я на работу программистом на удаленке. Мне прислали тест для проверки моих проф. знаний. Мне требовалось решить 18 задач и отправить результат работы обратно по почте.

Пока решал тест пришлось пару задач я пропустить. В них я не до конца понимал, что требуется.


Javascript-джедай #28 - Регулярные выражения

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

Если кому-то пригодится моя работа буду рад.

Если что-то не понятно, пишите комменты.

1. Дан набор чисел. Необходимо найти в нём все числа меньше 4.

Пример: 1 0 2 9 3 8 4 7 5 6 8 9 10 11 -1 -65 432 3 74

Здесь при решении я не использовал регулярные выражения

$txt = '1 0 2 9 3 8 4 7 5 6 8 9 10 11 -1 -65 432 3 74'; $var_txt = explode(" ", $txt); foreach ($var_txt as $key => $value) { if ($value < 4) echo ' , '.$value.' '; } //Решение: , 1 , 0 , 2 , 3 , -1 , -65 , 3

2. Дана строка произвольной длины. В строке перечислены разнообразные символы, буквы разных алфавитов и прочее. Необходимо получить все буквы русского алфавита, а также все числа от 0 до 6.

Пример: 4504569ук432534345345890456.43=3503245axc4521kdx230k023то94о289076с2

$str = '4504569ук432534345345890456.43=3503245axc4521kdx230k023то94о289076с2'; $str = iconv('windows-1251','utf-8',$str); // у меня не понимал русские пока не преобразовал. Работал в денвере WIN7x64 preg_match_all("/[0-6А-Яа-я]/",$str, $res); echo ' Решение: '; foreach ($res[0] as $value) { echo ' , '.$value; } //результат //Решение: , 4 , 5 , 0 , 4 , 5 , 6 , С , Р , 4 , 3 , 2 , 0 , 4 , 5 , 6 , 4 , 3 , 3 , 2 , 4 , 5 , 4 , 5 , 2 , 1 , 2 , 3 , 0 , 0 , 2 , 3 , С , Р , 4 , Р , 2 , 0 , 6 , С , 2

3. Дана строка произвольной длины, состоящая из одинаковых символов. Требуется написать два рег. выражения, которые бы возвращали первый символ и всю строку, соответственно.

Пример: «11111111111111».

$str = '11111111111111'; preg_match("/.{1}/",$str, $res); echo ' Первый символ: '.$res[0]; preg_match("/.*/",$str, $res); echo ' Вся строка: '.$res[0];

4. Дана строка «a1 b3 a8 c2 a9 d7 a4 e5 a3 f8 a0 g1».

Требуется написать ОДНО регулярное выражение, которое бы сматчило только числа согласно следующему условию: если перед числом стоит буква «a», то это число должно быть меньше 5, иначе – больше либо равно 5.

НЕ РЕШЕНО

5. Дана произвольная html-страница, необходимо получить содержимое всех тегов div, внутри которых находится минимум 5 подряд идущих цифр.

//Например: " <div>asd 764 1234457 абвы</div> <div>asd абвы</div> <div>asd 764 1257 абвы</div> ". $str = ' <div>asd 764 1234457 абвы</div> <div>asd абвы</div> <div>asd 764 1257 абвы</div> '; preg_match_all("! <div>(.*?[0-9]{5}.*?)</div> !",$str, $res); echo ' Решение: '; foreach ($res[0] as $value) { echo ' , '.$value; } //Решение: , asd 764 1234457 абвы

6. Дан текст. Необходимо найти в нём все слова, состоящие из 5 букв.

Пример текста: «дождь лопата два школа арбуз стройка пять дом голова бутан город шпала».

$str = 'дождь лопата два школа арбуз стройка пять дом голова бутан город шпала'; //$str = iconv('windows-1251','utf-8',$str); $str = ' '.$str.' '; //Добавил пробелы $str = str_replace(" ", " ", $str); preg_match_all("/\s([а-я]{5})\s/",$str, $res); echo ' Решение: '; foreach ($res[0] as $value) { echo ' , '.$value; } /* Решение: , дождь , школа , арбуз , бутан , город , шпала */

7. Дано множество строк (каждая строка – с новой строки), состоящих из чисел, разделённых пробелом. Необходимо найти все строки, в которых 5-е число было бы таким же, как и 18-е, а также являлось бы чётным числом и было больше 9.

//имеем набор чисел 1-15 в виде нескольких строк $str = '10 12 6 14 10 4 7 3 4 10 10 7 1 11 11 2 14 10 14 8 8 15 2 7 14 9 12 13 15 2 11 8 7 7 12 4 3 7 3 2 8 3 5 6 1 6 12 2 14 5 12 14 6 3 4 8 5 15 10 13 12 6 13 1 10 2 14 3 13 7 5 9 2 5 3 14 8 10 2 13 8 5 8 11 2 11 9 15 6 5 14 2 6 15 12 7 6 7 2 5 1 9 13 2 9 15 2 10 12 14 4 6 15 2 6 10 14 10 14 13 2 7 10 5 15 7 3 6 9 7 7 4 14 9 7 15 6 1 11 4 10 2 1 7 4 9 14 11 1 2 8 6 13 1 5 10 8 14 7 10 3 6 7 14 11 4 10 2 4 2 1 2 1 5 9 13 15 6 15 14 '; //получил все строки preg_match_all ("/(.*?)\n/", $str,$res); foreach ($res[0] as $value) { //разбиваю строку на числа preg_match_all ("/\s?[0-9]*\s/", $value,$num_array); $var5 = (int)$num_array[0][4]; $var18 = (int)$num_array[0][17]; //строка, в которой 5-е число такоеже как и 18-е, и больше 9 и оно четное if ($var5 == $var18 and $var5 > 9 and ($var5%2)==0) { echo ' '.$value; } } //результат работы /* 10 12 6 14 10 4 7 3 4 10 10 7 1 11 11 2 14 10 14 8 8 15 2 7 14 9 12 13 15 2 12 6 13 1 10 2 14 3 13 7 5 9 2 5 3 14 8 10 2 13 8 5 8 11 2 11 9 15 6 5 */

8. Дан текст. Необходимо найти в нём все слова, содержащие букву «а».

Пример текста: «дождь лопата два школа арбуз стройка пять дом голова бутан город шпала».

$str = 'дождь лопата два школа арбуз стройка пять дом голова бутан город шпала'; preg_match_all("/\s*[а-я]*\s?/",$str, $res); //нашел все слова в строке echo ' Решение: '; foreach ($res[0] as $value) { if (strrpos($value, 'а') == true) // ищем букву echo ' , '.$value; } /* Решение: , лопата , два , школа , стройка , голова , бутан , шпала */

9. Дана строка, содержащая имя человека, и дано регулярное выражение: «/(?#Имя)[А-Я][а-я]+\s(?#Отчество)[А-Яа-я]+\s(?#Фамилия)(?:[а-я]+)/». Необходимо изменить последнюю подмаску (следующую за комментарием «Фамилия») так, чтобы регулярное выражение сработало и вернуло бы всю строку (изменять или добавлять символьные классы нельзя).

Пример имени: «Иван Семенович Петров».

echo ' Решение: "/(?#Имя)[А-Я][а-я]+\s(?#Отчество)[А-Яа-я]+\s(?#Фамилия)(?[а-я]+)/" ';

10. Дан текст. Требуется написать регулярное выражение, которое бы матчило все строки, НЕ начинающиеся с числа «2».

//Пример текста: 1 http://www.yandex.ru 2 http://lenta.ru 3 www.google.com 02 facebook.com 36 twitter.com 12 www.imdb.com 1 blizzard.com 2 http://kinopoisk.ru 21 ozon.ru 0029 http://www.bicotender.ru';

НЕ РЕШЕНО

11. Дан набор тегов, необходимо получить содержимое всех тегов div, которые НЕ вложены в другие теги div. Учесть, что в тег div может быть вложено неограниченное количество других тегов div (рекурсивно) – требуется получить всё содержимое самого внешнего тега div.

Пример текста:

<div>Блок1</div> <div style="display:none;">Блок2</div> <div><h1>Заголовок</h1>Блок3</div> <table> <tr><td> <div>Вложенный <div>блок <div>4</div> </div> и ещё чуть-чуть. </div> </td> </tr> </table>'; //Решить можно было бы используя http://simplehtmldom.sourceforge.net/ //подгружаем библиотеку //require_once 'library/simplehtmldom.php'; //создаём новый объект //$html = new simple_html_dom(); //загружаем в него данные //$html = file_get_html($str2); //Ищем все <div> //$ret = $html->find('div'); //пример можно глянуть тут http://web2033.com/parsing-php-simple-html-dom/ //но я использовал свой алгоритм + регулярные выражения // исходная строка из задания для работы $str2 = ' <div>Блок1</div> <div style="display:none;">Блок2</div> <div> <h1>Заголовок</h1> блока3</div> <table> <tr> <td> <div> Вложенный <div> блок <div>4</div> </div> и ещё чуть-чуть.</div> </td> </tr> </table>'; //echo $str2; $str2 = str_replace(" style=\"display:none;\"", "",$str2); //убираю стиль // находим все дивы preg_match_all("/ <div> /",$str2, $res); $id = 0; // количество блоков div $pos = 0; // позиция //пронумеруем их <div1> <div2> и т.д. но закрывающие теги не трогаем foreach ($res[0] as $value) { $id++; $pos = strpos($str2,' <div> '); // смотрю позицию где тег в строке $str2 = substr_replace($str2,'<div'.$id.'>',$pos,5); // вставляю на его место тег с номером } //echo $str2; // ЗАДАЧА необходимо получить содержимое всех тегов //<div> //, которые НЕ вложены в другие теги //<div> // все просто надо найти дивы по номерам <div1..> и содержимым в котором нет других тегов DIV. Закрываются они также тегом </div> for ($i = 1; $i <= $id; $i++){ preg_match_all("!<div".$i.">.*?</div> !",$str2, $res); foreach ($res[0] as $value) { $count = substr_count ($value,'<div'); //смотрю сколько div у нас есть. Если 1 то нет вложенных if ($count == 1) echo ' , '.$value; } } //Результат работы: <div1>Блок1</div> , <div2>Блок2</div> , <div3> <h1>Заголовок</h1> блока3</div> , <div6>4</div> // ЗАДАЧА требуется получить всё содержимое самого внешнего тега //<div>. Я так понимаю это Див в котором Максимальное количество вложенных DIV // если нет, то я не верно решил $counter = 0; // для запоминания макс количества $number = 0; // номер тега с максимальным вложением тегов for ($i = 1; $i <= $id; $i++){ preg_match_all("!<div".$i.">.*?</div> *?.*?</div> *?.*?!",$str2, $res); foreach ($res[0] as $value) { $count = substr_count ($value,'<div'); //смотрю сколько div у нас есть. Если 1 то нет вложенных if ($counter<=$count) { $counter = $count; $number = $i; } } } echo 'Div с номером '.$number.' имеет '.($counter-1).' вложенных Div'; //Div с номером 4 имеет 2 вложенных Div // <div> Вложенный <div> блок <div>4</div> </div> и ещё чуть-чуть.</div> //Ну и выведем его на экран preg_match_all("!<div".$number.">.*?</div> *?.*?</div> *?.*?!",$str2, $res); echo ' '.$res[0][0]; //Можно было конечно удалить все лишние теги по краям, но я оставил для наглядности

12. Дана html страница сблоками:

Внутренний блок 1

Какой-то текст 2

Какой-то текст 3

Внутренний блок 3

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

Регулярное выражение должно отрабатывать быстро даже при очень большой вложенности тегов.’;

$str2 =' //строка с html кодом <table> <tbody> <tr> <td> <div> <h1>Блок 1</h1> <div>Внутренний блок 1</div> </div></td> <td> <div> <h1>Блок 2</h1> Какой-то текст 2 </div></td> </tr> <tr> <td> <div> Какой-то текст 3 <h1>Блок 3</h1> <div><strong>Внутренний блок</strong> 3</div> </div></td> </tr> </tbody> </table> '; // находим все дивы preg_match_all("/ <div> /",$str2, $res); $id = 0; // количество блоков div $pos = 0; // позиция //пронумеруем их и т.д. но закрывающие теги не трогаем foreach ($res[0] as $value) { $id++; $pos = strpos($str2,' <div>'); // смотрю позицию где тег в строке $str2 = substr_replace($str2,'&lt;div'.$id.'&gt;',$pos,5); // вставляю на его место тег с номером }//echo $str2; // ищу div без вложений for ($i = 1; $i &lt;= $id; $i++){ preg_match_all("!&lt;div".$i."&gt;.*? </div> !",$str2, $res); foreach ($res[0] as $value) { $count = substr_count ($value,'&lt;div'); //смотрю сколько div у нас есть. Если 1 то нет вложенных if ($count == 1) echo ' , '.$value; } } //результат работы //Внутренний блок 1 </div> , <strong>Внутренний блок</strong> 3 </div> //также div`ы не вырезал для наглядности результата

13. Дан текст. Необходимо найти в нём все слова, состоящие из 5 букв и содержащие букву «а».

Пример текста: «дождь лопата два школа арбуз стройка пять дом голова бутан город шпала»‘;

$str = 'дождь лопата два школа арбуз стройка пять дом голова бутан город шпала'; $str = ' '.$str.' '; //Добавил пробелы $str = str_replace(" ", " ", $str); preg_match_all("/\s([а-я]{5})\s/",$str, $res); echo ' Решение: '; foreach ($res[0] as $value) { if (strrpos($value, 'а') == true) // ищем букву echo ' , '.$value; } //Решение: , школа , арбуз , бутан , шпала

14. Дан текст. Необходимо найти все предложения, в которых НЕ встречается слово «два». Предложения разделены точками. Точка используется исключительно как знак окончания предложения. Все предложения начинаются с заглавной буквы и больше заглавных букв в себе не содержат.

Пример текста:

Два на два – четыре. Три на три – девять. Два на четыре – восемь. Четыре на пять – двадцать. Восемь на два – шестнадцать. Семь на восемь – пятьдесят шесть. Шесть на четыре – двадцать четыре. Пять на два – десять.

$str = 'Два на два – четыре. Три на три – девять. Два на четыре – восемь. Четыре на пять – двадцать. Восемь на два – шестнадцать. Семь на восемь – пятьдесят шесть. Шесть на четыре – двадцать четыре. Пять на два – десять.'; preg_match_all("/([А-Я])(.*?)\./",$str, $res); echo ' Решение: '; foreach ($res[0] as $value) { echo ' '.$value; } /* Решение: Два на два – четыре. Три на три – девять. Два на четыре – восемь. Четыре на пять – двадцать. Восемь на два – шестнадцать. Семь на восемь – пятьдесят шесть. Шесть на четыре – двадцать четыре. Пять на два – десять. */

15. Дан html. Необходимо получить содержимое всех тегов «P», которые находятся в закомментированных блоках.

//готовим данные $str = ' Комментарий в html коде <!-- комментарий . еще один. --> <!-- коммент 3 . четвертый 4. --> '; //данный пример работает если комментарий умещен в одну строку //получаем комментарии preg_match_all("/<!--(.*?)-->/",$str, $res); $p = ''; foreach ($res[0] as $value) { //получаем содержимое тега P preg_match_all("! (.*?) !",$value, $p); foreach ($p[0] as $teg_p) { echo ' '.strip_tags($teg_p, ''); } } /* РЕШЕНИЕ: комментарий . еще один. коммент 3 . четвертый 4. */

16. Дан SQL-запрос SELECT с непредсказуемым форматированием, но валидный. Получить в одну строку список всех столбцов, выбираемых запросом (звездочку преобразовывать в имена не нужно: все равно не получится). Учесть, что в именах столбцов могут быть такие вещи, как from, join, `inner join` и даже `from from from join cross outer from`’;

надо найти все что между select и последним словом FROM.

как правила имена задаются ковычками рядом с выбираемым столбцом, но и столбец может быть c ковычками, также между ними ОБЯЗАН быть пробел.

//пример запроса SELECT f1 `from`, `f2` `join`, f3 `inner join`, f4 `from from from join cross outer from` FROM users; $str = "SELECT f1 `from`,`f2` `join`,f3 `inner join`,f4 `from from from join cross outer from` FROM users;"; //$str = str_replace(" `", " ", $str); //echo ' '.$str; preg_match_all("/(^`.*?`)?\s`(.*?)`/",$str, $res); foreach ($res[0] as $value) { echo ' '.$value; } /*результат работы `from` `join` `inner join` `from from from join cross outer from` */

17. Дан html с множеством тегов. Требуется проверить, имеет ли каждый тег соответствующую закрывающуюся пару либо, если тег одиночный, оканчивается ли он на «/>». Html-комментарии, а также конструкции вида 123”> можно не учитывать.

// проверять будем <div></div> <h1></h1> т.е. теги без классов // решить данную задачу можно разными способами. Я выбрал самый простой. Так как у каждого тега должен быть закрывающий // я решил посчитать количество тегов открывающих и закрывающих. Их должно быть одинаковое количество. Если есть расхождения значит тег либо не открыт, либо не закрыт. // возьмем для примера этот текст" $html =' <table> <tbody> <tr> <td> <div> <h1>Блок 1</h1> <div>Внутренний блок 1 </div> </div></td> <td> <div> <h1>Блок 2</h1> Какой-то текст 2 </div></td> </tr> <tr> <td> <div> Какой-то текст 3 <h1>Блок 3</h1> <div><strong>Внутренний блок</strong> 3</div> </div></td> </tr> </tbody> </table> '; //найдем все открывающие теги которые есть в коде preg_match_all("/&lt;([a-zA-Z0-9]*)&gt;/",$html, $res); //убираю повторения. Для убыстрения работы. Потомучто в массиве $res несколько одних и тех же тегов. Например $res[0] = array_unique($res[0]);foreach ($res[0] as $value) { //посчитаю сколько тегов есть открывающих $begin_count_teg = substr_count ($html,$value); //делаю из отквающего тега закрывающий $value = str_replace("&lt;", " $close_count_teg) //открытых больше чем закрытых echo ' Тег: '.$value.' необходимо проверить он не зарыт'; } //результат работы //Тег: необходимо проверить либо он не зарыт. И он действительно не закрыт в исходной строке $html. // //Проверяю если тег одиночный, оканчивается ли он на «/&gt;» //снова беру все теги только одиночные например preg_match_all("/&lt;([a-zA-Z0-9]*)\s/",$html, $res); $res[0] = array_unique($res[0]); // убираю лишние теги foreach ($res[0] as $value) { //найденный тег пробую найти в коде в виде правильно написанного. Если не найду значит не имеет он на концу /&gt; $count = substr_count ($html,$value.'/&gt;'); if ($count&lt;1) { echo 'Тег: '.$value.' /&gt; Не закрыт'; } } // результат работы //Тег: Не закрыт

18. Дан текст. Требуется ко всем конструкциям вида «(.[\w\d]+)+» присоединить произвольную подстроку. Данная конструкция может быть обрамлена с обеих сторон знаками «%»: в этом случае подстрока должна быть присоединена после первого «%» (перед первой точкой), в остальных случаях подстроку нужно присоединить просто в начало конструкции. Пример текста: «fff .key1.key4.kkk22% %.key2.key4% %.key1 key5 .key6.key7.tumba».

// исходная строка $str = 'fff .key1.key4.kkk22% %.key2.key4% %.key1 key5 .key6.key7.tumba'; // рандомный текст для добавления к знаку процента % $random_txt = md5( microtime() . mt_rand()); preg_match_all("/(%?.[\w\d]+%?)+/",$str, $res); echo ' Решение: '; foreach ($res[0] as $value) { // первое условие // конструкция может быть обрамлена с обеих сторон знаками «%»: в этом случае подстрока должна быть присоединена после первого «%» (перед первой точкой) // проверяем обрамлена она % или нет if ($value[0]=='%' and substr($value, -1)=='%'){ //подставляем в начало нашу сгенерированную строку $value = str_replace("%.", '%'.$random_txt.".", $value); }else{ // второе условие //в остальных случаях подстроку нужно присоединить просто в начало конструкции. Что я и сделал $value = $random_txt.$value; } echo ' '.$value; } /*Результат работы 266aad662801151d58dcbdb263481f51fff 266aad662801151d58dcbdb263481f51.key1.key4.kkk22% %266aad662801151d58dcbdb263481f51.key2.key4% 266aad662801151d58dcbdb263481f51%.key1 key5 266aad662801151d58dcbdb263481f51.key6.key7.tumba */ </div>

rss