Регулярні вирази

  1. приклади шаблонів
  2. Дужки в регулярних виразах
  3. Бекслеші
  4. Спеціальні конструкції в регулярки
  5. мануал
  6. завдання
  7. Завдання на перевірку телефонів
  8. повторимо
  9. Завдання (поки без картинок)
  10. Опечаточнікі

Регулярні вирази - це спеціальні шаблони для пошуку підрядка в тексті. З їх допомогою можна вирішити одним рядком такі завдання: «перевірити, чи містить рядок цифри», «знайти в тексті всі адреси email», «замінити кілька йдуть підряд знаків питання на один».

Почнемо з одного народної програмістської мудрості:

Деякі люди, стикаючись з проблемою, думають: «Ага, я розумний, я вирішу її за допомогою регулярних виразів». Тепер у них дві проблеми.

Це досить-таки об'ємний і складний урок. Але, якщо ти дійшов до сюди, то ти здатний подужати і це. Просто майже теорію, не треба запам'ятовувати, а коли дійдеш до задачок, повернися і проясни незрозумілі моменти. Ну або відкрий мануал - там ця тема детально роз'яснюється. Посилання: http://www.php.net/manual/ru/reference.pcre.pattern.syntax.php

приклади шаблонів

Почнемо з пари простих прикладів. Перший вираз на зображенні нижче шукає послідовність з 3 букв, де перша буква це «до», друга - будь-яка російська буква і третя - це «т» без урахування регістру (наприклад, «кіт» або «КОТ» підходить під цей шаблон). Другий вираз шукає в тексті час в форматі 12:34.

Будь-яке вираження починається з символу-обмежувача (delimiter по англ.). Як нього зазвичай використовують символ /, але можна використовувати і інші символи, які не мають спеціального призначення в регулярки, наприклад, ~, # або @. Альтернативні роздільники використовують, якщо в вираженні може зустрічатися символ /. Потім йде сам шаблон рядки, яку ми шукаємо, за ним другий обмежувач і в кінці може йти одна або кілька букв-прапорів. Вони задають додаткові опції при пошуку тексту. Ось приклади прапорів:

  • i - каже, що пошук повинен вестися без урахування регістру літер (за замовчуванням регістр враховується)
  • u - каже, що вираз і текст, за яким йде пошук, ісплоьзуют кодування utf-8, а не тільки латинські букви. Без нього пошук російських (і будь-яких інших нелатинських) символів може працювати некоректно, тому варто ставити його завжди.

Сам шаблон складається зі звичайних символів і спеціальних конструкцій. Ну наприклад, буква «до» в регулярки позначає саму себе, а ось символи [0-5] означають «в цьому місці може бути будь-яка цифра від 0 до 5». Ось повний список спеціальних символів (в мануалі php їх називають метасимволи), а всі інші символи в регулярке - звичайні:

Нижче ми розберемо значення кожного з цих символів (а також пояснимо чому буква «е» винесена окремо в першому вираженні), а поки спробуємо застосувати наші регулярки до тексту і подивитися, що вийде. В php є спеціальна функція preg_match ($ regexp, $ text, $ match), яка приймає на вхід регулярку, текст і порожній масив. Вона перевіряє, чи є в тексті подстрока, що відповідає даному шаблоном і повертає 0, якщо немає, або 1, якщо вона є. А в переданий масив в елемент з індексом 0 кладеться перше знайдене збіг з регулярки. Напишемо просту програму, яка застосовує регулярні вирази до різних рядках:

Код Результат $ regexp = "/ к [а-яё] т / ui"; // рядки, до яких ми будемо по черзі застосовувати регулярку $ lines = [ 'рудий кіт', 'рудий кріт', 'кит і кіт']; foreach ($ lines as $ line) {echo "Рядок: $ line \ n"; // сюди буде вміщено перший // збіг з шаблоном $ match = []; if (preg_match ($ regexp, $ line, $ match)) {echo "+ Знайдено слово '{$ match [0]}' \ n"; } Else {echo "- Нічого не знайдено \ n"; }} Рядок: рудий кіт + Знайдено слово 'кіт' Рядок: рудий кріт - Нічого не знайдено Рядок: кит і кіт + Знайдено слово 'кит'

Познайомившись з прикладом, вивчимо регулярні вирази більш докладно.

Дужки в регулярних виразах

Давай повторимо, що позначають різні види дужок:

  • Фігурні дужки a {1,5} задають число повторень попереднього символу - в цьому прикладі вираз шукає від 1 до 5 йдуть підряд букв «a»
  • Квадратні дужки [a-c0-5xyz] означають «один будь-який з цих символів», в даному випадку - букви a, b, c, x, y, z або цифра від 0 до 5. Усередині квадратних дужок не працюють інші спецсимволи на кшталт | або * - вони позначають звичайний символ. Якщо в квадратних дужках на початку варто символ ^ то сенс змінюється на протилежний: «будь-який один символ, крім зазначених» - наприклад [^ ac] означає «один будь-який символ, крім a, b або c».
  • Круглі дужки групують символи і вирази. Наприклад в вираженні abc + знак «плюс» відноситься тільки до букви c і цей вислів шукає слова на кшталт abc, abcc, abccc. А якщо поставити дужки a (bc) + то квантіфіактор плюс відноситься вже до послідовності bc і вираз шукає слова abc, abcbc, abcbcbc

Примітка: в квадратних дужках можна вказувати діапазони символів, але пам'ятай, що російська буква е йде окремо від алфавіту і щоб написати «будь-яка російська буква», треба писати [а-яё].

Бекслеші

Якщо ти дивився інші підручники з регулярними виразами, то напевно помітив, що бекслеш всюди пишуть по-різному. Десь пишуть один бекслеш: \ d, а тут в прикладах він повторений 2 рази: \\ d. Чому?

Мова регулярних виразів вимагає писати бекслеш один раз. Однак в рядках в одиночних і подвійних лапках в PHP бекслеш теж має особливе значення: мануал про рядки . Ну наприклад, якщо написати $ x = "\ $"; то PHP сприйме це як спеціальну комбінацію і вставить в рядок тільки символ $ (і движок регулярних виразів не впізнає про бекслеше перед ним). Щоб вставити в рядок послідовність \ $, ми повинні подвоїти бекслеш і записати код у вигляді $ x = "\\ $" ;.

З цієї причини в деяких випадках (там, де послідовність символів має спеціальний сенс в PHP) ми зобов'язані подвоювати бекслеш:

  • Щоб написати в регулярке \ $, ми пишемо в коді "\\ $"
  • Щоб написати в регулярке \\, ми подвоюємо кожен бекслеш і пишемо "\\\\"
  • Щоб написати в регулярке бекслеш і цифру (\ 1), бекслеш треба подвоїти: "\\ 1"

В інших випадках один або два бекслеша дадуть один і той же результат: "\\ d" і "\ d" вставлять в рядок пару символів \ d - в першому випадку 2 бекслеша це послідовність для вставки бекслеша, у другому випадку спеціальної послідовності немає і символи вставити як є. Перевірити, які символи вставити в рядок, і що побачить движок регулярних виразів, можна за допомогою echo: echo "\ $" ;. Так, складно, а що поробиш?

Спеціальні конструкції в регулярки

  • \ D шукає одну будь-яку цифру, \ D - один будь-який символ, крім цифри
  • \ W відповідає одній будь букві (будь-якого алфавіту), цифрі або знаку підкреслення _. \ W відповідає будь-якому символу, крім букви, цифри, знака підкреслення.

Також, є зручне умова для вказівки на кордон слова: \ b. Ця конструкція позначає, що з одного боку від неї повинен стояти символ, який є буквою / цифрою / знаком підкреслення (\ w), а з іншого боку - не є. Ну, наприклад, ми хочемо знайти в тексті слово «кіт». Якщо ми напишемо регулярку / кіт / ui, то вона знайде послідовність цих букв в будь-якому місці - наприклад, всередині слова «скотина». Це явно не те, що ми хотіли. Якщо ж ми додамо умова кордону слова в регулярку: / \ bкот \ b / ui, то тепер шукатися буде тільки окрема слово «кіт».

мануал

Також, є корисний сайт Regex101 , Де можна протестувати свою регулярку і перевірити, що вона знайде в тексті. Пам'ятай, що на тому сайті бекслеші треба писати рівно один раз, і ставити прапор u не потрібно.

завдання

Напиши програму, яка отримує на вхід автомобільний номер, і перевіряє, чи правильно він введений. Автомобільний номер має вид «а123вг», тобто починається з букви, за якою йде 3 цифри, і ще 2 букви. Ніяких сторонніх символів бути в ньому не повинно.

Цю програму треба вирішити за допомогою preg_match () і регулярного виразу. Протестувати його ти можеш наприклад на сайті Regex101.

Завдання на перевірку телефонів

Дан текст, який по ідеї повинен бути номером телефону у вигляді 8- (911) -506 56 56 (тобто людина може ввести не тільки цифри, але і дужки, мінуси, може щось ще). Але в реальності, користувач може замість номера написати що завгодно. Напиши скрипт для перевірки правильності введеного номера ( «8 (911) -506 56 56» - правильний номер, «8-911-50-656-56» - правильний, «89115065656» - правильний, «02» - неправильний, «89115065656 покликати Люду »- неправильний).

Завдання треба перевірити на великому числі телефонів, щоб переконатися що твій код правильний. Для цього давай додамо в програму тести, щоб відразу було видно, вірно все працює чи ні. Зроби 2 списку номерів (правильні і немає), додай їх в програму і напиши цикл, який їх по черзі проганяє через регулярку і перевіряє, що вони визначаються як треба (якщо немає - треба вивести, який саме номер не розпізнається правильно).

Ось список номерів:

// Правильні: $ correctNumbers = [ '84951234567', '+74951234567', '8-495-1-234-567', '8 (8122) 56-56-56', '8-911-1234567', ' 8 (911) 12 345 67 ',' 8-911 12 345 67 ',' 8 (911) - 123 - 4567 ',' + 7 999 123 4567 ',' 8 (999) 1234567 ',' 8 999 123 4567 ']; // Неправильні: $ incorrectNumbers = [ '02', '84951234567 покликати Люсю', '849512345', '849512345678', '8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888 -88 ',' 84951a234567 ',' 8495123456a ',' +1 234 5678901 ', / * невірний код країни * /' +8 234 5678901 ', / * або 8 або +7 * /' 7 234 5678901 '/ * немає + * /];

Також, на regex101 https://regex101.com/r/qF7vT8/3 вже введені номери і можна простестіровать свою регулярку. Пам'ятай що на цьому сайті треба писати бекслеш один раз, наприклад \ s, а не \\ s. Прапор m там стоїть щоб ^ і $ в регулярке позначали «початок і кінець будь-якого рядка», а не «початок і кінець всього тексту». Прапор g (його немає в PHP, він тільки на цьому сайті) означає що треба шукати всі збіги з регулярки, а не тільки перше.

Підказка: не треба будувати складних виразів і передбачати всі можливі комбінації символів. Достатньо написати: спочатку йде +7 або 8, за ними рівно 10 цифр, між якими може бути будь-яке число дужок, мінусів, прогалин

Достатньо написати: спочатку йде +7 або 8, за ними рівно 10 цифр, між якими може бути будь-яке число дужок, мінусів, прогалин

повторимо

  • preg_match знаходить перший збіг з регулярними виразом і перевіряє, чи відповідає текст або частину виразу
  • preg_match_all знаходить все фрагменти тексту, відповідні регулярке
  • preg_split розбиває текст на масив частин по регулярному виразу
  • preg_replace замінює в тексті частини, відповідні регулярке, на даний рядок

Завдання (поки без картинок)

  • На вхід скрипта дан самі ввели номер телефону у вигляді 8-911-404-44-11 або +7 (812) 6786767 (на початку 8 або +7, потім йдуть 10 цифр і, можливо, якісь символи). Тобто, як і в минулому завданні, людина вводить номер як хоче. Треба перевірити номер на правильність і привести будь-який номер до єдиного формату 89114044411 (тобто, замінити +7 на 8 і викинути все сміття на кшталт прогалин, дужок і мінусів, крім цифр)
  • Автозаміна. Напиши скрипт, який замінює певне слово на інше (наприклад, слово «дурень» на «хороша людина» в фразі «ти дурень»). Скрипт повинен не пропускати слово, якщо воно написано буквами в різному регістрі (дурень), із заміною російських букв на схожі англійські (а -> a), або через прогалини ( «ти - д у р а к»)
  • Дан текст, що містить в собі email'и (адреси пошти на кшталт [email protected]). Напиши скрипт, що виводить все email, що зустрічаються в цьому тексті
  • «Grammar Nazi». Напиши скрипт, який перевіряє текст на наявність злісних помилок:
    • немає пробілу після коми, крапки з комою, знак оклику, знака питання, двокрапки
    • «Жи» або «ши» написано з літерою и
    • в тексті є слово «координально» або «сдесь», «зделал», «зделаю», «зделан»
    • в тексті є слова «а» або «але» без коми перед ними.
    • (Можеш додати ще кілька правил, якщо добре знаєш російську мову)

    У разі виявлення помилки скрипт повинен писати повідомлення про це і виводити шматок тексту з помилкою (щоб було зрозуміло, що не так).

  • Якщо ти зробив завдання про Grammar Nazi, зроби скрипт, котори замість повідомлення про помилки буде мовчки їх виправляти.

Опечаточнікі

Як тобі напевно відомо, багато людей, що займають державні посади, витрачають свої сили аж ніяк не на поліпшення ситуації в своєму місті чи регіоні, а на придумування різноманітних схем по переміщенню ввірених їм бюджетних коштів в свої кишені.

Наприклад, державні органи, які хочуть провести закупівлі, зобов'язані організувати публічні торги і розмістити оголошення про них на сайті держзакупівель. Щоб стати на перешкоді всім бажаючим взяти участь у тендері (і щоб віддати замовлення «своїм людям» і отримати потім від них в свою кишеню частина грошей), вони замінюють в описі замовлення деякі російські букви на схожі на них латинські. Таким чином, не попереджені заздалегідь організації не зможуть знайти оголошення через пошук і взяти участь в конкурсі.

Давай спробуємо застосувати наші знання мови PHP для того, щоб вивести шахраїв на чисту воду.

Завдання: дан текст, що містить слова російською та англійською мовами. У деяких словах частина російських букв замінена на схожі на них латинські, і навпаки. Напиши програму, яка знаходить все такі слова, виводить їх і виділяє квадратними дужками першу замінену букву.

Для перевірки працездатності, спробуй застосувати програму до тексту з поля «Найменування замовлення» на сторінці (обережно, спойлер!) Http://zakupki.gov.ru/pgz/public/action/orders/info/common_info/show?notificationId=5193640 або http://zakupki.gov.ru/pgz/public/action/orders/info/common_info/show?notificationId=5138013 ололо хто б повірив!

Додаткове завдання: додай в програму автоматичне виправлення знайдених «помилок».

Підказки для дурненький: слова з помилками знайти легко: це слово, яке починається з одного або декількох російських букв, за якими йде латинський. Ну або починається з латинської, за якою йде російська. Досить мінімальних знань регулярних виразів, щоб написати рішення.

PS На сайті програмістів коміксів xkcd є комікс про регулярні вирази: переклад , оригінал (англ.) .

далі: Повторимо?

-----

Куди вводити код? Що треба скачати? Читай перший урок .

Є питання? Постав Гуглу або автору.

Подобається урок? Лайкать, репоста, запрошуй друзів, пости котів і Канако, йшли добра, вирішуй завдання, допомагай новачкам! Кнопок для лайка немає, хто хоче зарепостіть, завжди може зробити це ручками.

Зв'язок з автором? Я хочу переодягнути його в плаття школярки і одружитися на ній. Ящик codedokode (кіт) gmail.com чекає ваших листів. А вконтактік і фейсбучек чекають ваших лайків. Але відповідь на банальні питання краще шукати в Гуглі або на stackoverflow.

Я вирішив задачу !!! Молодець, роби наступний урок

Ideone не працює! 11 Ну так відкрий Гугл і знайди сайти на кшталт https://repl.it/languages/php, http://phptester.net/, http://sandbox.onlinephpfunctions.com/, http: // codepad .org / або http://www.runphponline.com/. Не лінуйся.

Чому так багато реклами? Всю рекламу на сайті ставить юкоз (безкоштовний хостинг же), а не я.

На сайті встановлена ​​система Google Analytics (і ще кілька аналогічних систем від Юкоз). Дані про твоє IP-адресу, відвідуваних сторінках, часу відвідування відправляються в Google Corporation, США. Хочу знати, хто і навіщо сюди заходить. Повір, інші сайти роблять точно так же. Всі сайти пишуть логи.

Чому?
Так, складно, а що поробиш?
Ru/pgz/public/action/orders/info/common_info/show?
Ru/pgz/public/action/orders/info/common_info/show?
Що треба скачати?
Є питання?
Подобається урок?
Зв'язок з автором?
Чому так багато реклами?