PHP 5 about PHP 5 старт PHP 5 установка PHP 5 синтаксис PHP 5 змінні PHP 5 echo і print PHP 5 типи даних PHP 5 strings PHP 5 константи PHP 5 оператори PHP 5 if...else...elseif PHP 5 switch PHP 5 цикл while PHP 5 for і foreach PHP 5 функції PHP 5 масиви PHP 5 сортування масивів PHP 5 superglobals PHP 5 форми input PHP 5 форми обробка PHP 5 форми - обов'язкові поля PHP 5 форми - перевірка електронної пошти і URL РНР 5 форми заповнення PHP 5 багатовимірні масиви PHP 5 час і дата PHP 5 include PHP 5 файли обробка PHP 5 файли Open/Read/Close PHP 5 файли створення / запис PHP 5 файли завантаження PHP MySQL бази даних PHP MySQL Підключення PHP MySQL Створення бази даних PHP MySQL Створення таблиці PHP MySQL вставка даних PHP MySQL Отримання ідентифікатора останнього доданого запису PHP MySQL вставка кількох записів PHP MySQL Підготовлені вирази PHP MySQL відображення даних з таблиці PHP MySQL Видалення даних PHP MySQL оновлення даних PHP MySQL обмежити вибірку даних PHP регулярні вирази 1 PHP регулярні вирази 2 PHP регулярні вирази 3 PHP регулярні вирази 4 PHP ООП PHP ООП class PHP ООП модифікатори доступу PHP ООП extends PHP ООП статичні методи і властивості, константи PHP ООП abstract PHP ООП interface PHP альтернативний синтаксис керуючих конструкцій

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


Обчислення з preg_replace

До цього ми не розглядали preg_replace() , тому розглянемо швидкий приклад:

<?php
$string = 'We will replace the word foo';

// міняємо `foo` на `bar`
$string = preg_replace('#foo#', 'bar', $string);

echo $string;       //  We will replace the word bar 
?>

Приклад замінить в рядку foo на bar . У таких простих замінах доцільніше використовувати функції обробки рядків str_replace() , які швидше справляються з простими завданнями, але мають деякі обмеження, наприклад не підтримують юнікод.


Заглядання вперед (Look Aheads)

Можливість регулярних виразів "заглянути вперед" шаблону для визначення подальших збігів.
"Підглядання вперед" буває позитивне і негативне

Розглянемо спочатку заглядання вперед з запереченням. Позначається в шаблоні символами " ?! ".
Корисно при пошуку шаблону, що стоїть попереду від збігу, який нам потрібен.

приклад:

<?php
$string = 'I live in the whitehouse';

// try to match white not followed by house
if (preg_match('#white+(?!house)#i', $string)) {    //  false

// if we find the word white, not followed by house
    echo 'true';
} else {
    echo 'false';
}
?>

Результат скрипта:

false

Тому що слово " white " слідує за словом " house ".
Подамо блюдо під іншим соусом:

<?php

$string = 'I live in the white house';

// try to match white not followed by house
if (preg_match('#white+(?!house)#i', $string)) {    //  true
    
// if we find the word white, not followed by house
    echo 'true';
} else {
    echo 'false';
}
?>

Результат скрипта:
збіг

Є збіг, тому що слово " white " не слідує відразу ж за словом " house " (як в " whitehouse ")

Позитивне заглядання вперед " ?= "

<?php
$string = 'This is an example eg: foo';

// try to match eg followed by a colon
if (preg_match("#eg+(?=:)#", $string, $match)) {
    print_r($match);    //  Array ( [0] => eg )
} else {
    echo 'false';
}
?>

Результат скрипта:
Array ( [0] => eg )

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


Заглядання назад (Look Behinds)

Дозволяє переглянути рядок назад і визначити наявність збігів з шаблоном.
Також розділяється на позитивне і негативне.
Позитивне - записується " ?<= "

Розберемо приклад:

<?php
$string = 'I live in the whitehouse';

// try to match house preceded by white
if (preg_match('#(?<=white)house#i', $string)) {    //  true
    
// if we find the word white, not followed by house
    echo 'true';
} else {
    echo 'false';
}
?>

Результат скрипта:
true

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

Якщо ми хочемо, щоб " house " НЕ слідував за словом " white "?
Використовуємо відємне заглядання назад - " ?<! "

<?php
/*** a simple string ***/
$string = 'I live in the whitehouse';

/*** try to match house preceded by white ***/
if (preg_match('#(?<!white)house#i', $string)) {        //  false

    /*** if we find the word white, not followed by house ***/
    echo 'true';
} else {
    /*** if no match is found ***/
    echo 'false';
}
?>

Результат скрипта:
false

Тому що негативне заглядання не знайшло шаблону " house " з шаблоном " white " на початку його.
Давайте змінимо колір " house ".

<?php
$string = 'I live in the bluehouse';

// ищем `house` с непредшествующим `white`
if (preg_match('#(?<!white)house#i', $string)) {            //  true
    
    /*** if we find the word white, not followed by house ***/
    echo 'true';
} else {
    /*** if no match is found ***/
    echo 'false';
}
?>

Ми змінили " whitehouse " на " bluehouse " і тепер наша регулярка спрацювала, тому що шаблон " white " не виявлено перед " house ".

За замовчуванням регулярки жадібні, це означає що квантіфікатори (яке слово страшне)  * , + , ?   "пожирають" стільки символів скільки можуть.

*   -   0 і більше символів, same as {0, }
+   -   1 і більше символів, same as {1, }
?   -   0 або 1 символ, same as {0,1} 

приклад

<?php
/*** 4 x and 4 z chars ***/
$string = "xxxxzzzz";

/*** greedy regex ***/
preg_match('#^(.*)(z+)$#', $string, $matches);

/*** results ***/
echo $matches[1];   //  xxxxzzz
echo "<br />";
echo $matches[2];   //  z
?>

Перший патерн ( . * ) Збігся з усіма чотирма " x " і трьома з чотирьох символів " z ".
Спрацювала жадібність - шаблон забрав стільки символів, скільки було в шуканої рядку.
Простіше простого допомогти перестати квантіфікатору бути жадібними, додавши " ? " до квантіфікатора як в прикладі:

<?php
/*** string of characters ***/
$string = "xxxxzzzz";

/*** a non greedy match ***/
preg_match('#^(.*?)(z+)$#', $string, $matches);

/*** show the matches ***/
echo $matches[1];   //  xxxx
echo "<br />";
echo $matches[2];   //  zzzz
?>

Тепер $matches[1] містить чотири " x " символи і $matches[2] чотири символи " z ".
Тому що квантіфікатор " ? " змінив поведінку шаблону з "взяти якомога БІЛЬШЕ" на "взяти якомога МЕНШЕ".

Щоб зробити нежадібним весь шаблон, використовуємо модифікатор " U ".

<?php
/*** string of characters ***/
$string = "xxxxzzzz";

/*** a non greedy match ***/
preg_match('#^(.*)(z+)$#U', $string, $matches);

/*** show the matches ***/
echo $matches[1];   //  xxxx
echo "<br />";
echo $matches[2];   //  zzzz

?>

Результат як в попередньому прикладі.


Підводні камені з ? і U

Важливо зауважити, що модифікатор " U " не тільки робить пошук нежадібним, він інвертує поведінку жадібності квантіфікатора " ? ".
Якщо використовувався квантіфікатор " ? " і одночасно модифікатор " U ", дія " ? " буде інвертована.

<?php
/*** string of characters ***/
$string = "xxxxzzzz";

/*** a non greedy match ***/
preg_match('#^(.*?)(z+)$#U', $string, $matches);

/*** show the matches ***/
echo $matches[1];   //  xxxxzzz
echo "<br />";
echo $matches[2];   //  z
?>

Результат скрипта:
xxxxzzz
z

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

Тому як роздільник можна взяти будь-який символ, наприклад # , @ , ^ ...

<?php
/*** get the host name from a url ***/
preg_match('#^(?:https://)?([^/]+)#i', "https://www.site4study.com/", $matches);

/*** show the host name ***/
echo $matches[1];   //  www.site4study.com
?> 

приклади

<?php

// the string to match against
$string = 'The cat sat on the mat' ;

// match the beginning of the string
echo preg_match ( "/^The/" , $string ) ;

// match the end of the string
// returns 1
echo preg_match ( "/mat\z/" , $string ) ;

// match anywhere in the string
// returns 0 as no match was found for dog.
echo preg_match ( "/dog/" , $string ) ;
?>

Пошук кількох шаблонів

<?php

// the string to match against
$string = 'The cat sat on the matthew';

// matches the letter "a" followed by zero or more "t" characters
echo preg_match("/at*/", $string);

// matches the letter "a" followed by a "t" character that may or may not be present
echo preg_match("/at?/", $string);

// matches the letter "a" followed by one or more "t" characters
echo preg_match("/at+/", $string);

// matches a possible letter "e" followed by one of more "w" characters anchored to the end of the string
echo preg_match("/e?w+ \z /", $string);

// matches the letter "a" followed by exactly two "t" characters
echo preg_match("/at{2}/", $string);

// matches a possible letter "e" followed by exactly two "t" characters
echo preg_match("/e?t{2}/", $string);

// matches a possible letter "a" followed by exactly 2 to 6 "t" chars (att attt atttttt)
echo preg_match("/at{2,6}/", $string);

?> 

Запам'ятайте, preg_match()  повертає тільки 0 або 1, і зупиняється після першого успішного знаходження шаблону.

Щоб знайти всі збіги - використовуйте preg_match_all() .


Шпаргалка

Спец послідовності
 
\w - Any “word” character (a-z 0-9 _)
    \W - Any non “word” character
\s - Whitespace (space, tab CRLF)
    \S - Any non whitepsace character
\d - Digits (0-9)
    \D - Any non digit character
. - (Period) – Any character except newline
 
Мета символи
 
^ - Start of subject (or line in multiline mode)
    $ - End of subject (or line in multiline mode)
    [ - Start character class definition
    ] - End character class definition
    | - Alternates, eg (a|b) matches a or b
( - Start subpattern
    ) - End subpattern
\ - Escape character
 
Квантифікатори
 
    n- Zero or more of n
    n+ - One or more of n
    n? - Zero or one occurrences of n
    {n} - n occurrences exactly
    {n,} - At least n occurrences
    {n,m} - Between n and m occurrences (inclusive)
 
Модифікатори
 
    i - Case Insensitive
    m - Multiline mode - ^ and $ match start and end of lines
    s - Dotall - . class includes newline
    x - Extended– comments and whitespace
    e - preg_replace only – enables evaluation of replacement as PHP code
    S - Extra analysis of pattern
    U - Pattern is ungreedy
    u - Pattern is treated as UTF-8
 
Точкові умови
 
\b - Word boundary
\B - Not a word boundary
\A - Start of subject
\Z - End of subject or newline at end
\z - End of subject
\G - First matching position in subject
 
Умови
 
(?=) - Positive look ahead assertion foo(?=bar) matches foo when followed by bar
(?!) - Negative look ahead assertion foo(?!bar) matches foo when not followed by bar
(?<=) - Positive look behind assertion (?<=foo)bar matches bar when preceded by foo
(?<!) - Negative look behind assertion (?<!foo)bar matches bar when not preceded by foo
(?>) - Once-only subpatterns (?>\d+)bar Performance enhancing when bar not present
(?(x)) - Conditional subpatterns
(?(3)foo|fu)bar - Matches foo if 3rd subpattern has matched, fu if not
(?#) - Comment (?# Pattern does x y or z)

Іменоване "захоплення"

Можливість регулярних виразів іменувати ключі в результуючому масиві збігів.

Записується: ( ?<Name> ), ( ?'Name' ) або ( ?P<name> ).
Раніше підтримувався тільки такий синтаксис: ( ?P<name> ). [<php5.2.2]

<?php
$text = 'Name: Andrew, Age: 25';
print_r(preg_match('/Name: (.+), Age: (\d+)/', $text, $matches));                   //  1
print_r(preg_match('/Name: (?P<Name>.+), Age: (?P<Age>\d+)/', $text, $matches));    //  1
?>

Результат скрипта:
array ( 'Name' => 'рядок', 'Age' => 'число')


Заміна строки по шаблону з допомогою функції preg_replace

В даному прикладі ми створюємо нову строку по заданому шаблону в змінній $replacement , ми считуємо значення з дужок (\w+) - перший елемент $1 , (\d+) - другий елемент $2 і так далі, по регулярному виразу вставляємо знайдені значення в шаблон з допомогою $1, $2, $3, ... .

<?php
$string = 'April 15, 2019';
$pattern = '#(\w+) (\d+), (\d+)#i'; //  1   ==  $1   April,  2 == $2   15,   3 == $3   2019, ...
$replacement = 'now: day: $2 month: ${1} year: $3';    //  now: day: 15 month: April year: 2019

echo preg_replace($pattern, $replacement, $string); //  now: day: 15 month: April year: 2019
?>

Заміна через callback-функцію

В php є можливість вказати функцію зворотного виклику для збігів, якщо нам потрібно проробити з ними незвичайні речі. Для цього використовується preg_replace_callback .

Розглянемо приклад

<?php
$text = "April fools day is 04/01/2002\n";
$text .= "Last christmas was 12/24/2001\n";

// функція зворотнього виклику
function next_year($matches)
{
    // $matches[0] -  повне входження шаблона
    // $matches[1] - входження першої підмаски,
    // заключеної в круглі скобки, і так далі...
    return $matches[1] . ($matches[2] + 1);
}

echo preg_replace_callback(
    "#(\d{2}/\d{2}/)(\d{4})#",
    "next_year",
    $text);

// результат:
// April fools day is 04/01/2003
// Last christmas was 12/24/2002
?>

Cheatsheet regex

Регулярні вирази шпаргалка для початківців

Наш партнер:
beta test mp3 playlist downloader