Кроме того, с помощью
Одно из распространенных применений
/^\w+([\.\w]+)*\w@\w((\.\w)*\w+)*\.\w{2,3}$/
Выглядит, конечно, жутко, но зато работает. И если уметь пользоваться этим механизмом виртуозно, то жить становится легче.
Вернемся к нашему определению
Давайте подумаем, что представляет собой корректный e-mail–адрес. Это набор букв, цифр и символов подчеркивания, после которых идет специальный символ "собака" .) и две или три буквы, указывающие на зону домена, к которой принадлежит почтовый ящик (ru, com, org и т.д.). Приведенное выше
Механизм
В дальнейшем изложении термины
(разбиение строки на подстроки), (нахождение подстроки), (замена всех вхождений подстроки). Возникает вопрос – зачем придумывать что-то еще?
Основное преимущество
/\d{3}-\d{2}-\d{2}/m
В PHP существует два различных механизма для обработки
Основные функции для работы с и , где:
pattern –
string – строка, в которой производится поиск;
result – содержит массив результатов (нулевой элемент массива содержит соответствие всему шаблону, первый – первому "захваченному"
flags – необязательный параметр, определяющий то, как упорядочены результаты поиска.
Эти функции осуществляют поиск по шаблону и возвращают информацию о том, сколько раз произошло совпадение. Для это 0 (нет совпадений) или 1, поскольку поиск прекращается, как только найдено первое совпадение. Функция производит поиск до конца строки и поэтому находит все совпадения. Все точные совпадения содержатся в первом элементе массива result у каждой из этих функций (для этот элемент – тоже массив).
Про "захват" элементов будет рассказано в разделе, посвященном
Аналогом является булева функция
Функция возвращает TRUE, если совпадение найдено, и FALSE – в противном случае.
Приводимые далее примеры можно тестировать на перечисленных функциях. Например, так:
<?
//строка, в которой нужно что-то найти
$str = "Мой телефонный номер: ".
"33-22-44. Номер моего редактора: ".
"222-44-55 и 323-22-33";
//шаблон, по которому искать.
//Задает поиск семизначных номеров.
$pattern = "/\d{3}-\d{2}-\d{2}/m";
//функция, осуществляющая поиск
$num_match = preg_match_all ($pattern,
$str, $result);
//вывод результатов поиска
for ($i=0;$i<$num_match;$i++)
echo "Совпадение $i: ".
$result[0][$i]."<br>";
?>
Строгое определение
В дальнейшем это описание будет расширено.
Например, в /\d{3}-\d{2}-\d{2}/m символ " / "является разделителем, \d{3}-\d{2}-\d{2} – непосредственно m –
Мощь
Одним из основных \." означает просто точку.
Другое назначение
\n – cимвол перевода строки;
\e – символ escape;
\t – cимвол табуляции;
\xhh – символ в шестнадцатеричном коде, например \x41 есть буква A и т.д.
Еще одно назначение
\d – любая десятичная цифра ( 0-9 );
\D – любой символ, не являющийся десятичной цифрой;
\s – любой пустой символ (пробел или табуляция);
\S – любой символ, не являющийся пустым;
\w – символ, используемый для написания Perl-слов (это буквы, цифры и символ подчеркивания), так называемый "словарный символ";
\W – несловарный символ (все символы, кроме определяемых \w ).
Что имеется в виду под "символьным типом"? Просто каждый
Пример использования приведенных выше
/\d\d\d plus \d is \w\w\w/
Это plus, любая цифра, затем is и слово из трех словарных символов. В частности, данному 123 plus 3 is sum ", " 213 plus 4 is 217 ".
Вообще различают два множества
Квадратные скобки [ ] применяются для ^, то значением символьного класса могут быть только символы, НЕ перечисленные внутри скобок.
Примеры:
[абвгд] задает один из символов а, б, в, г, д, а класс [^абвгд] задает любой символ, кроме а, б, в, г, д.[2бул]ки], то это выражение интерпретируется как один из символов 2, б, у, л, за которым следует строка ки], потому что первая встретившаяся закрывающая квадратная скобка (разбор происходит слева направо) заканчивает определение символьного класса. То есть это 2ки], бки], уки] или лки].[0-9А-Яа-я] можно задать любую букву или цифру.Примеры (^ и $)
$str = "11 aaa bbb ".
"ccc 22 ddd ".
"eee ggg 33";
| Значение | |
|---|---|
\ |
Переходный символ со множеством назначений |
^ |
Отрицание класса, но только если это первый символ
(например, " ^\d " задает все, кроме цифр) |
- |
Задает 0-9 " задает
все цифры, " A-Z " – все латинские буквы) |
] |
Вычисляет символьный класс |
/\d\d/m может быть сопоставлено следующим подстрокам: 11, 22, 33. Если в начале ^, то совпадения ищутся в начале строки, поэтому выражение /^\d\d/m найдет только 11.
Когда в конце $, поиск производится в конце строки, поэтому выражение /\d\d$/m найдет только 33.
Шаблону же /^\d\d\d$/ будет удовлетворять строка, целиком состоящая из трехзначного числа (т.е. она и начинается и заканчивается этим числом).
1.htm.<?
//считываем файл в строку
$str = file_get_contents('1.htm');
$pattern = "!^<[^/]+>!mU";
// осуществляем поиск
$n = preg_match_all ($pattern,
$str, $res);
// выводим результаты
for ($i=0;$i<$n;$i++)
echo htmlspecialchars($res[0][$i]).
"<br>";
?>
| Значение | |
|---|---|
\ |
Переходный символ со множеством назначений |
^ |
Объявляет начало объекта (или строки в
многострочном режиме). То есть этот символ определяет, что
искомый текст должен находиться в начале строки.
Альтернатива: " \A " |
$ |
Объявляет конец объекта (или строки в
многострочном режиме). То есть этот символ определяет, что
искомый текст должен находиться в конце строки.
Альтернативы: " \Z ", " \z " |
| . | Совпадает с любым символом, кроме символа перевода строки (по умолчанию) |
[ |
Начинает определение символьного класса |
] |
Заканчивает определение символьного класса |
| |
Разделяет перечисление |
( |
Начинает |
) |
Заканчивает |
| ? | Расширяет значение " ( ", 0 или 1,
и |
* |
0 или больше повторений ( |
+ |
1 или больше повторений ( |
{ |
Начинает минимальный/максимальный |
} |
Заканчивает минимальный/максимальный |
Шаблон ограничен восклицательными знаками. Первая " ^ " значит, что мы ищем совпадения в начале строк, потом идет символ " < " – его и ищем в строке, после него должно идти все, что угодно, кроме [^/] " ), " + " говорит, что стоящий перед ним символ повторяется один и более раз и заканчивается все это символом " > ". Таким образом, выделяются все теги в начале строк.
<?
//считываем файл в строку
$str = file_get_contents('1.htm');
$pattern = "!\s[А-Я][А-Яа-я]+".
"\s([А-Я]\.\s*)([А-Я]\.\s*)$!m";
// шаблон ограничен восклицатель-
// ными знаками, m – модификатор,
// включающий многострочный режим.
// Первый \s означает, что перед
// фамилией должен идти пустой
// символ (например, пробел).
// [А-Яа-я] задает одну из букв
// алфавита в любом регистре, а в
// комбинации со знаком плюс
// определяет, что эта буква
// повторяется один и более
// раз. Следующий \s означает, что
// между фамилией и инициалами
// должен быть пробел.
// Далее идет подвыражение,
// определяющее инициалы.
// Это буква от А до Я, после
// которой стоит точка ('\.')
// Экранируем точку, чтобы
// избавиться от ее специального
// значения. После буквы с точкой
// может идти или не идти пробел
// или несколько. Вся конструкция
// повторяется минимум два раза.
// Последний символ $ означает,
// что фамилия с инициалами
// должны находиться в конце
// строки.
// осуществляем поиск
$n = preg_match_all ($pattern,
$str, $res);
// выводим результаты
for ($i=0;$i<$n;$i++)
echo htmlspecialchars($res[0][$i]).
"<br>";
?>
Примеры ( | и .)
<?
$str = "Доцент Смирнов совершил ".
"открытие. Его учителем была ".
"профессор Иванова. ".
"Этим открытием Смирнов ".
"завоевал себе степень ".
"доктора. Раньше он был ".
"только кандидат.";
$pattern = "/(профессор|доцент)".
"\s[А-Я][А-Яа-я]+(\s|\.)/i";
// осуществляем поиск
$n = preg_match_all ($pattern, $str,
$res);
// выводим результаты
for ($i=0;$i<$n;$i++)
echo htmlspecialchars($res[0][$i]).
"<br>";
?>
| " позволяет задавать (профессор|доцент) ". После звания через пробел фамилия человека, которому оно принадлежит, – для этого существует комбинация " \s[А-Я][А-Яа-я]+ ". После фамилии идет либо опять пробел, либо точка, если это конец предложения. Получаем опять два (\s|\.) " (здесь точка экранируется
В нескольких примерах мы уже использовали
В
Например, шаблон
жар(кое|птица)совпадает с одним из слов "
жаркое ", " жарптица " и " жар ". Тогда как без скобок это было бы " жаркое ", " птица " и пустая строка.Например, имеется такой шаблон:
победитель получит
((золотую|позолоченный)
(медаль|кубок))
и строка, в которой ищутся совпадения с этим шаблоном: " победитель получит золотую медаль ". Тогда кроме этой фразы будут еще захвачены и выданы как результаты поиска следующие совпадения в золотую медаль ", " золотую ", " медаль ", пронумерованные 1, 2, 3 соответственно.Однако это не всегда удобно. Для того чтобы избавиться от "захватывающего" эффекта ?:". Тогда это
победитель получит
((?:золотую|позолоченный)
(медаль|кубок))
Тогда в условиях предыдущего примера получим искомую строку " победитель получит золотую медаль " и строки " золотую медаль ", " медаль ", пронумерованные 1 и 2 соответственно.
Если в html-файле название находится после <body> и отделено от него только пробелами или переводами строк, заключено в тег <h1> и после него тоже может идти сколько-то пробелов и переводов строк, то его можно найти с помощью следующего скрипта:
<?
//считываем файл в строку
$str = file_get_contents('1.htm');
$pattern = "/<body.*?>[\n\s]*<h1>".
"(.*?)<\/h1>[\n\s]*/m";
// осуществляем поиск
$n = preg_match_all ($pattern, $str, $res);
echo $res[1][0]; // выводим заголовок
?>
Заметим, что здесь выводится первое захваченное
В предыдущих примерах мы часто писали комбинации типа \d\d. Это значит, что цифра должна повторяться два раза. А что же делать, если повторений очень много или мы не знаем, сколько именно? Оказывается, нужно использовать специальные
Повторения описываются с помощью так называемых
x{1,3}
говорит о том, что символ "x" должен повторяться минимум один, а максимум три раза. Соответственно этому шаблону удовлетворяют строки: x, xx, xxx.
Если второй параметр отсутствует, но запятая есть, то повторений может быть сколько угодно. Таким образом,
[aeuoi]{2,}
значит, что любой из символов " a ", " e ", " u ", " o ", " i " в строке может повторяться два и более раз, а
\d{3}
задает ровно три цифры.
Исходя из исторических традиций три наиболее часто встречающихся
* эквивалентно {0,} – то есть это ноль и более повторений;
+ эквивалентно {1,} – то есть это одно и более повторений;
? эквивалентно {0,1} – то есть это ноль или одно повторение.
Есть еще один важный момент, на который стоит обратить внимание при изучении * ), совпадение произойдет со строкой, содержащей наибольшее число повторений указанного символа. Это может создать проблемы, например, при попытке выделить комментарии в программе на языке Cи или PHP. Комментарии в Cи и PHP записываются между символами /* и */, внутри которых тоже могут встречаться символы * и /. И попытка выявить Си-комментарии с помощью шаблона
/\* .* \*/
в строке
/* первый комментарий */
не комментарий
/* второй комментарий */
не увенчается успехом из-за .* " (будет найдена также строка "не комментарий").
Для решения этой проблемы нужно написать знак вопроса после
/\* .*? \*/
успешно выделяет Си-комментарии.
В PHP существует
<?
//Рассмотрим html-файл, где имеется
//следующая строка:
$str = "<div id=1>Привет</div> ".
"<p>Текст, не заключенный в тег ".
"div</p><div id=2>Пока</div>";
// Если мы хотим найти текст,
// содержащийся между тегами div,
// естественно написать такой шаблон:
$pattern = "!<div id=1>.*</div>!si";
// Но этот шаблон слишком "жадный"
// и захватит также и текст,
// заключенный в нашем примере между
// тегами <p>. Чтобы этого избежать,
// нужно написать следующий шаблон,
// отличающийся только наличием знака
// вопроса, который запрещает
// квантификатору быть "жадным".
$pattern1 = "!<div id=1>.*?</div>!si";
// Запускаем поиск в строке $str
// совпадений с шаблонами
// $pattern и $pattern1
$s = preg_match_all ($pattern, $str,
$res);
$js = preg_match_all ($pattern1,
$str, $res1);
//выводим результаты поиска
// функция htmlspecialchars позволяет
// выводить html без
// его обработки браузером
echo "Жадный шаблон:".
htmlspecialchars($res[0][0]).
"<br>";
echo "Нежадный шаблон:".
htmlspecialchars($res1[0][0]);
?>
Результаты работы скрипта:
"Жадный" шаблон:<div id=1>Привет</div> <p>Текст,не заключенный в тег div</p> <div id=2>Пока</div> "Нежадный" шаблон:<div id=1>Привет</div>
Теперь мы в принципе можем решить задачу выделения содержания из html-файла, если оно заключено в теге <div id=content>. Предлагаем читателям проделать это самостоятельно.
Еще один немаловажный элемент
| Обозначение | Описание |
|---|---|
i ( PCRE_CASELESS ) |
Если указан этот |
m ( PCRE_MULTILINE ) |
По умолчанию строка, подающаяся на вход
интерпретатору |
s ( PCRE_DOTALL ) |
Если установлен этот |
x ( PCRE_EXTENDED ) |
Заставляет интерпретатор игнорировать
пробелы между символами в шаблоне, за
исключением пробелов, # вне символьного
класса и |
U ( PCRE_UNGREEDY ) |
Этот |
В последующих разделах обсуждаются более сложные конструкции работы с
\1 ) называется
(ответствен|надеж)ный проявляет \1ность
совпадет со строками " ответственный проявляет ответственность ", " надежный проявляет надежность " и не совпадет со строкой " ответственный проявляет надежность ".
\A, \Z, ^, $ и т.д. Более сложные
Существует два типа
(?= для позитивных (?! для негативных. Например,
\w+(?=;)
совпадает со словом, заканчивающимся точкой с запятой (не включая точку с запятой в результат поиска), и
foo(?!bar)
совпадает с любым появлением foo, после которого нет bar. Как все происходит? Берем строку и ищем в ней foo. Как только нашли, заглядываем вперед (текущая позиция при этом не меняется) и смотрим, идет ли далее bar. Если нет, то совпадение с шаблоном найдено, иначе продолжаем поиск.
(?!foo)bar
не найдет все вхождения bar, перед которыми нет foo, потому что оно ?!foo всегда верно.
(?<=, негативные – с (?<! .
(?<!foo)bar
находит все появления bar, перед которыми нет foo.
В начале лекции мы хотели научиться находить в html-файле упоминание об авторе. Это можно сделать с помощью
<?
//считываем файл в строку
$str = file_get_contents('1.htm');
$pattern = "/(?<=Автор:)\s[А-Я]".
"[а-я]*\s([А-Я]\.\s*){1,2}/m";
// осуществляем поиск
$n = preg_match_all ($pattern, $str, $res);
// выводим результаты
for ($i=0;$i<$n;$i++)
echo htmlspecialchars($res[0][$i]).
"<br>";
?>
Часть
Дату можно вычислить похожим образом. Оставляем это в качестве упражнения.
Как в любом языке программирования, в
(?(условие)шаблон_выполняемый_если_
условие_верно)
(?(условие)шаблон_если_условие_верно
|шаблон_если_условие_неверно)
Существует два типа условий. Если текст между круглыми скобками состоит из последовательности цифр, то условие удовлетворяется, если захваченное
( \( )? [^()]+ (?(1) \) )
Первая часть этого
Вторая часть совпадает с одним или более символами, не заключенными в круглые скобки.
Третья часть ( ", то условие верно и вычисляется условный шаблон, а именно требуется наличие закрывающей круглой скобки. В противном случае
Если условие – не последовательность цифр, то оно должно быть
(?(?=[^a-z]*[a-z])\d{2}-[a-z]{3}-\d{2}
|\d{2}-\d{2}-\d{2})
Условие здесь – позитивное (\d{2}-[a-z]{3}-\d{2}), иначе – по второму (\d{2}-\d{2}-\d{2}). Этому шаблону удовлетворяют строки двух типов: dd- или dd-dd-dd, где d – любая цифра, a – любая буква.
Итак, мы рассмотрели механизм
Кроме того, с помощью
Одно из распространенных применений
/^\w+([\.\w]+)*\w@\w((\.\w)*\w+)*\.\w{2,3}$/
Выглядит, конечно, жутко, но зато работает. И если уметь пользоваться этим механизмом виртуозно, то жить становится легче.
Вернемся к нашему определению
Давайте подумаем, что представляет собой корректный e-mail–адрес. Это набор букв, цифр и символов подчеркивания, после которых идет специальный символ "собака" .) и две или три буквы, указывающие на зону домена, к которой принадлежит почтовый ящик (ru, com, org и т.д.). Приведенное выше
Механизм
В дальнейшем изложении термины
(разбиение строки на подстроки), (нахождение подстроки), (замена всех вхождений подстроки). Возникает вопрос – зачем придумывать что-то еще?
Основное преимущество
/\d{3}-\d{2}-\d{2}/m
В PHP существует два различных механизма для обработки
Основные функции для работы с и , где:
pattern –
string – строка, в которой производится поиск;
result – содержит массив результатов (нулевой элемент массива содержит соответствие всему шаблону, первый – первому "захваченному"
flags – необязательный параметр, определяющий то, как упорядочены результаты поиска.
Эти функции осуществляют поиск по шаблону и возвращают информацию о том, сколько раз произошло совпадение. Для это 0 (нет совпадений) или 1, поскольку поиск прекращается, как только найдено первое совпадение. Функция производит поиск до конца строки и поэтому находит все совпадения. Все точные совпадения содержатся в первом элементе массива result у каждой из этих функций (для этот элемент – тоже массив).
Про "захват" элементов будет рассказано в разделе, посвященном
Аналогом является булева функция
Функция возвращает TRUE, если совпадение найдено, и FALSE – в противном случае.
Приводимые далее примеры можно тестировать на перечисленных функциях. Например, так:
<?
//строка, в которой нужно что-то найти
$str = "Мой телефонный номер: ".
"33-22-44. Номер моего редактора: ".
"222-44-55 и 323-22-33";
//шаблон, по которому искать.
//Задает поиск семизначных номеров.
$pattern = "/\d{3}-\d{2}-\d{2}/m";
//функция, осуществляющая поиск
$num_match = preg_match_all ($pattern,
$str, $result);
//вывод результатов поиска
for ($i=0;$i<$num_match;$i++)
echo "Совпадение $i: ".
$result[0][$i]."<br>";
?>
Строгое определение
В дальнейшем это описание будет расширено.
Например, в /\d{3}-\d{2}-\d{2}/m символ " / "является разделителем, \d{3}-\d{2}-\d{2} – непосредственно m –
Мощь
Одним из основных \." означает просто точку.
Другое назначение
\n – cимвол перевода строки;
\e – символ escape;
\t – cимвол табуляции;
\xhh – символ в шестнадцатеричном коде, например \x41 есть буква A и т.д.
Еще одно назначение
\d – любая десятичная цифра ( 0-9 );
\D – любой символ, не являющийся десятичной цифрой;
\s – любой пустой символ (пробел или табуляция);
\S – любой символ, не являющийся пустым;
\w – символ, используемый для написания Perl-слов (это буквы, цифры и символ подчеркивания), так называемый "словарный символ";
\W – несловарный символ (все символы, кроме определяемых \w ).
Что имеется в виду под "символьным типом"? Просто каждый
Пример использования приведенных выше
/\d\d\d plus \d is \w\w\w/
Это plus, любая цифра, затем is и слово из трех словарных символов. В частности, данному 123 plus 3 is sum ", " 213 plus 4 is 217 ".
Вообще различают два множества
Квадратные скобки [ ] применяются для ^, то значением символьного класса могут быть только символы, НЕ перечисленные внутри скобок.
Примеры:
[абвгд] задает один из символов а, б, в, г, д, а класс [^абвгд] задает любой символ, кроме а, б, в, г, д.[2бул]ки], то это выражение интерпретируется как один из символов 2, б, у, л, за которым следует строка ки], потому что первая встретившаяся закрывающая квадратная скобка (разбор происходит слева направо) заканчивает определение символьного класса. То есть это 2ки], бки], уки] или лки].[0-9А-Яа-я] можно задать любую букву или цифру.Примеры (^ и $)
$str = "11 aaa bbb ".
"ccc 22 ddd ".
"eee ggg 33";
| Значение | |
|---|---|
\ |
Переходный символ со множеством назначений |
^ |
Отрицание класса, но только если это первый символ
(например, " ^\d " задает все, кроме цифр) |
- |
Задает 0-9 " задает
все цифры, " A-Z " – все латинские буквы) |
] |
Вычисляет символьный класс |
/\d\d/m может быть сопоставлено следующим подстрокам: 11, 22, 33. Если в начале ^, то совпадения ищутся в начале строки, поэтому выражение /^\d\d/m найдет только 11.
Когда в конце $, поиск производится в конце строки, поэтому выражение /\d\d$/m найдет только 33.
Шаблону же /^\d\d\d$/ будет удовлетворять строка, целиком состоящая из трехзначного числа (т.е. она и начинается и заканчивается этим числом).
1.htm.<?
//считываем файл в строку
$str = file_get_contents('1.htm');
$pattern = "!^<[^/]+>!mU";
// осуществляем поиск
$n = preg_match_all ($pattern,
$str, $res);
// выводим результаты
for ($i=0;$i<$n;$i++)
echo htmlspecialchars($res[0][$i]).
"<br>";
?>
| Значение | |
|---|---|
\ |
Переходный символ со множеством назначений |
^ |
Объявляет начало объекта (или строки в
многострочном режиме). То есть этот символ определяет, что
искомый текст должен находиться в начале строки.
Альтернатива: " \A " |
$ |
Объявляет конец объекта (или строки в
многострочном режиме). То есть этот символ определяет, что
искомый текст должен находиться в конце строки.
Альтернативы: " \Z ", " \z " |
| . | Совпадает с любым символом, кроме символа перевода строки (по умолчанию) |
[ |
Начинает определение символьного класса |
] |
Заканчивает определение символьного класса |
| |
Разделяет перечисление |
( |
Начинает |
) |
Заканчивает |
| ? | Расширяет значение " ( ", 0 или 1,
и |
* |
0 или больше повторений ( |
+ |
1 или больше повторений ( |
{ |
Начинает минимальный/максимальный |
} |
Заканчивает минимальный/максимальный |
Шаблон ограничен восклицательными знаками. Первая " ^ " значит, что мы ищем совпадения в начале строк, потом идет символ " < " – его и ищем в строке, после него должно идти все, что угодно, кроме [^/] " ), " + " говорит, что стоящий перед ним символ повторяется один и более раз и заканчивается все это символом " > ". Таким образом, выделяются все теги в начале строк.
<?
//считываем файл в строку
$str = file_get_contents('1.htm');
$pattern = "!\s[А-Я][А-Яа-я]+".
"\s([А-Я]\.\s*)([А-Я]\.\s*)$!m";
// шаблон ограничен восклицатель-
// ными знаками, m – модификатор,
// включающий многострочный режим.
// Первый \s означает, что перед
// фамилией должен идти пустой
// символ (например, пробел).
// [А-Яа-я] задает одну из букв
// алфавита в любом регистре, а в
// комбинации со знаком плюс
// определяет, что эта буква
// повторяется один и более
// раз. Следующий \s означает, что
// между фамилией и инициалами
// должен быть пробел.
// Далее идет подвыражение,
// определяющее инициалы.
// Это буква от А до Я, после
// которой стоит точка ('\.')
// Экранируем точку, чтобы
// избавиться от ее специального
// значения. После буквы с точкой
// может идти или не идти пробел
// или несколько. Вся конструкция
// повторяется минимум два раза.
// Последний символ $ означает,
// что фамилия с инициалами
// должны находиться в конце
// строки.
// осуществляем поиск
$n = preg_match_all ($pattern,
$str, $res);
// выводим результаты
for ($i=0;$i<$n;$i++)
echo htmlspecialchars($res[0][$i]).
"<br>";
?>
Примеры ( | и .)
<?
$str = "Доцент Смирнов совершил ".
"открытие. Его учителем была ".
"профессор Иванова. ".
"Этим открытием Смирнов ".
"завоевал себе степень ".
"доктора. Раньше он был ".
"только кандидат.";
$pattern = "/(профессор|доцент)".
"\s[А-Я][А-Яа-я]+(\s|\.)/i";
// осуществляем поиск
$n = preg_match_all ($pattern, $str,
$res);
// выводим результаты
for ($i=0;$i<$n;$i++)
echo htmlspecialchars($res[0][$i]).
"<br>";
?>
| " позволяет задавать (профессор|доцент) ". После звания через пробел фамилия человека, которому оно принадлежит, – для этого существует комбинация " \s[А-Я][А-Яа-я]+ ". После фамилии идет либо опять пробел, либо точка, если это конец предложения. Получаем опять два (\s|\.) " (здесь точка экранируется
В нескольких примерах мы уже использовали
В
Например, шаблон
жар(кое|птица)совпадает с одним из слов "
жаркое ", " жарптица " и " жар ". Тогда как без скобок это было бы " жаркое ", " птица " и пустая строка.Например, имеется такой шаблон:
победитель получит
((золотую|позолоченный)
(медаль|кубок))
и строка, в которой ищутся совпадения с этим шаблоном: " победитель получит золотую медаль ". Тогда кроме этой фразы будут еще захвачены и выданы как результаты поиска следующие совпадения в золотую медаль ", " золотую ", " медаль ", пронумерованные 1, 2, 3 соответственно.Однако это не всегда удобно. Для того чтобы избавиться от "захватывающего" эффекта ?:". Тогда это
победитель получит
((?:золотую|позолоченный)
(медаль|кубок))
Тогда в условиях предыдущего примера получим искомую строку " победитель получит золотую медаль " и строки " золотую медаль ", " медаль ", пронумерованные 1 и 2 соответственно.
Если в html-файле название находится после <body> и отделено от него только пробелами или переводами строк, заключено в тег <h1> и после него тоже может идти сколько-то пробелов и переводов строк, то его можно найти с помощью следующего скрипта:
<?
//считываем файл в строку
$str = file_get_contents('1.htm');
$pattern = "/<body.*?>[\n\s]*<h1>".
"(.*?)<\/h1>[\n\s]*/m";
// осуществляем поиск
$n = preg_match_all ($pattern, $str, $res);
echo $res[1][0]; // выводим заголовок
?>
Заметим, что здесь выводится первое захваченное
В предыдущих примерах мы часто писали комбинации типа \d\d. Это значит, что цифра должна повторяться два раза. А что же делать, если повторений очень много или мы не знаем, сколько именно? Оказывается, нужно использовать специальные
Повторения описываются с помощью так называемых
x{1,3}
говорит о том, что символ "x" должен повторяться минимум один, а максимум три раза. Соответственно этому шаблону удовлетворяют строки: x, xx, xxx.
Если второй параметр отсутствует, но запятая есть, то повторений может быть сколько угодно. Таким образом,
[aeuoi]{2,}
значит, что любой из символов " a ", " e ", " u ", " o ", " i " в строке может повторяться два и более раз, а
\d{3}
задает ровно три цифры.
Исходя из исторических традиций три наиболее часто встречающихся
* эквивалентно {0,} – то есть это ноль и более повторений;
+ эквивалентно {1,} – то есть это одно и более повторений;
? эквивалентно {0,1} – то есть это ноль или одно повторение.
Есть еще один важный момент, на который стоит обратить внимание при изучении * ), совпадение произойдет со строкой, содержащей наибольшее число повторений указанного символа. Это может создать проблемы, например, при попытке выделить комментарии в программе на языке Cи или PHP. Комментарии в Cи и PHP записываются между символами /* и */, внутри которых тоже могут встречаться символы * и /. И попытка выявить Си-комментарии с помощью шаблона
/\* .* \*/
в строке
/* первый комментарий */
не комментарий
/* второй комментарий */
не увенчается успехом из-за .* " (будет найдена также строка "не комментарий").
Для решения этой проблемы нужно написать знак вопроса после
/\* .*? \*/
успешно выделяет Си-комментарии.
В PHP существует
<?
//Рассмотрим html-файл, где имеется
//следующая строка:
$str = "<div id=1>Привет</div> ".
"<p>Текст, не заключенный в тег ".
"div</p><div id=2>Пока</div>";
// Если мы хотим найти текст,
// содержащийся между тегами div,
// естественно написать такой шаблон:
$pattern = "!<div id=1>.*</div>!si";
// Но этот шаблон слишком "жадный"
// и захватит также и текст,
// заключенный в нашем примере между
// тегами <p>. Чтобы этого избежать,
// нужно написать следующий шаблон,
// отличающийся только наличием знака
// вопроса, который запрещает
// квантификатору быть "жадным".
$pattern1 = "!<div id=1>.*?</div>!si";
// Запускаем поиск в строке $str
// совпадений с шаблонами
// $pattern и $pattern1
$s = preg_match_all ($pattern, $str,
$res);
$js = preg_match_all ($pattern1,
$str, $res1);
//выводим результаты поиска
// функция htmlspecialchars позволяет
// выводить html без
// его обработки браузером
echo "Жадный шаблон:".
htmlspecialchars($res[0][0]).
"<br>";
echo "Нежадный шаблон:".
htmlspecialchars($res1[0][0]);
?>
Результаты работы скрипта:
"Жадный" шаблон:<div id=1>Привет</div> <p>Текст,не заключенный в тег div</p> <div id=2>Пока</div> "Нежадный" шаблон:<div id=1>Привет</div>
Теперь мы в принципе можем решить задачу выделения содержания из html-файла, если оно заключено в теге <div id=content>. Предлагаем читателям проделать это самостоятельно.
Еще один немаловажный элемент
| Обозначение | Описание |
|---|---|
i ( PCRE_CASELESS ) |
Если указан этот |
m ( PCRE_MULTILINE ) |
По умолчанию строка, подающаяся на вход
интерпретатору |
s ( PCRE_DOTALL ) |
Если установлен этот |
x ( PCRE_EXTENDED ) |
Заставляет интерпретатор игнорировать
пробелы между символами в шаблоне, за
исключением пробелов, # вне символьного
класса и |
U ( PCRE_UNGREEDY ) |
Этот |
В последующих разделах обсуждаются более сложные конструкции работы с
\1 ) называется
(ответствен|надеж)ный проявляет \1ность
совпадет со строками " ответственный проявляет ответственность ", " надежный проявляет надежность " и не совпадет со строкой " ответственный проявляет надежность ".
\A, \Z, ^, $ и т.д. Более сложные
Существует два типа
(?= для позитивных (?! для негативных. Например,
\w+(?=;)
совпадает со словом, заканчивающимся точкой с запятой (не включая точку с запятой в результат поиска), и
foo(?!bar)
совпадает с любым появлением foo, после которого нет bar. Как все происходит? Берем строку и ищем в ней foo. Как только нашли, заглядываем вперед (текущая позиция при этом не меняется) и смотрим, идет ли далее bar. Если нет, то совпадение с шаблоном найдено, иначе продолжаем поиск.
(?!foo)bar
не найдет все вхождения bar, перед которыми нет foo, потому что оно ?!foo всегда верно.
(?<=, негативные – с (?<! .
(?<!foo)bar
находит все появления bar, перед которыми нет foo.
В начале лекции мы хотели научиться находить в html-файле упоминание об авторе. Это можно сделать с помощью
<?
//считываем файл в строку
$str = file_get_contents('1.htm');
$pattern = "/(?<=Автор:)\s[А-Я]".
"[а-я]*\s([А-Я]\.\s*){1,2}/m";
// осуществляем поиск
$n = preg_match_all ($pattern, $str, $res);
// выводим результаты
for ($i=0;$i<$n;$i++)
echo htmlspecialchars($res[0][$i]).
"<br>";
?>
Часть
Дату можно вычислить похожим образом. Оставляем это в качестве упражнения.
Как в любом языке программирования, в
(?(условие)шаблон_выполняемый_если_
условие_верно)
(?(условие)шаблон_если_условие_верно
|шаблон_если_условие_неверно)
Существует два типа условий. Если текст между круглыми скобками состоит из последовательности цифр, то условие удовлетворяется, если захваченное
( \( )? [^()]+ (?(1) \) )
Первая часть этого
Вторая часть совпадает с одним или более символами, не заключенными в круглые скобки.
Третья часть ( ", то условие верно и вычисляется условный шаблон, а именно требуется наличие закрывающей круглой скобки. В противном случае
Если условие – не последовательность цифр, то оно должно быть
(?(?=[^a-z]*[a-z])\d{2}-[a-z]{3}-\d{2}
|\d{2}-\d{2}-\d{2})
Условие здесь – позитивное (\d{2}-[a-z]{3}-\d{2}), иначе – по второму (\d{2}-\d{2}-\d{2}). Этому шаблону удовлетворяют строки двух типов: dd- или dd-dd-dd, где d – любая цифра, a – любая буква.
Итак, мы рассмотрели механизм
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.