Глава 8. Строки и
регулярные выражения
ГЛАВА 8
Строки и регулярные выражения
Возможности эффективной организации, поиска и распространения
информации давно представляли интерес для специалистов в области
компьютерных технологий. Поскольку информация в основном представляет
собой текст, состоящий из алфавитно-цифровых символов, разработка средств
поиска и обработки информации по шаблонам, описывающим текст, стала
предметом серьезных теоретических исследований.
Поиск по шаблону позволяет не только находить определенные фрагменты
текста, но и заменять их другими фрагментами. Одним из стандартных
примеров поиска по шаблону являются команды поиска/замены в текстовых
редакторах - например, в MS Word, Emacs и в моем любимом редакторе vi.
Всем пользователям UNIX хорошо известны такие программы, как sed, awk и
grep; богатство возможностей этих программ в значительной степени
обусловлено средствами поиска по шаблону. Механизмы поиска по шаблону
решают четыре основные задачи:
- поиск строк, в точности совпадающих с заданным шаблоном;
- поиск фрагментов строк, совпадающих с заданным шаблоном;
- замену строк и подстрок по шаблону;
- поиск строк, с которыми заданный шаблон не совпадает.
Появление Web породило необходимость в более быстрых и эффективных
средствах поиска данных, которые бы позволяли пользователям со всего мира
находить нужную информацию среди миллиардов web-страниц. Поисковые
системы, онлайновые финансовые службы и сайты электронной коммерции - все
это стало бы абсолютно бесполезным без средств анализа гигантских объемов
данных в этих секторах. Действительно, средства обработки строковой
информации являются жизненно важной составляющей практически любого
сектора, так или иначе связанного с современными информационными
технологиями. В этой главе основное внимание посвящено средствам обработки
строк в РНР. Мы рассмотрим некоторые стандартные строковые функции (в
языке их больше 60!), а из приведенных определений и примеров вы получите
сведения, необходимые для создания web-приложений. Но прежде чем
переходить к специфике РНР, я хочу познакомить вас с базовым механизмом,
благодаря которому становится возможным поиск по шаблону. Речь идет о
регулярных выражениях.
Регулярные выражения
Регулярные выражения лежат в основе всех современных технологий поиска
по шаблону. Регулярное выражение представляет собой последовательность
простых и служебных символов, описывающих искомый текст. Иногда регулярные
выражения бывают простыми и понятными (например, слово dog), но часто в
них присутствуют служебные символы, обладающие особым смыслом в синтаксисе
регулярных выражений, - например, <(?)>.*<\/.?>.
В РНР существуют два семейства функций, каждое из которых относится к
определенному типу регулярных выражений: в стиле POSIX или в стиле Perl.
Каждый тип регулярных выражений обладает собственным синтаксисом и
рассматривается в соответствующей части главы. На эту тему были написаны
многочисленные учебники, которые можно найти как в Web, так и в книжных
магазинах. Поэтому я приведу лишь основные сведения о каждом типе, а
дальнейшую информацию при желании вы сможете найти самостоятельно. Если вы
еще не знакомы с принципами работы регулярных выражений, обязательно
прочитайте краткий вводный курс, занимающий всю оставшуюся часть этого
раздела. А если вы хорошо разбираетесь в этой области, смело переходите к
следующему разделу.
Синтаксис регулярных выражений (POSIX)
Структура регулярных выражений POSIX чем-то напоминает структуру
типичных математических выражений - различные элементы (операторы)
объединяются друг с другом и образуют более сложные выражения. Однако
именно смысл объединения элементов делает регулярные выражения таким
мощным и выразительным средством. Возможности не ограничиваются поиском
литерального текста (например, конкретного слова или числа); вы можете
провести поиск строк с разной семантикой, но похожим синтаксисом -
например, всех тегов HTML в файле.
Простейшее регулярное выражение совпадает с одним литеральным символом
- например, выражение g совпадает в таких строках, как g, haggle и bag.
Выражение, полученное при объединении нескольких литеральных символов,
совпадает по тем же правилам - например, последовательность gan совпадает
в любой строке, содержащей эти символы (например, gang, organize или
Reagan).
Оператор | (вертикальная черта) проверяет совпадение одной из
нескольких альтернатив. Например, регулярное выражение php | zend
проверяет строку на наличие php или zend.
Квадратные скобки
Квадратные скобки ([ ]) имеют особый смысл в контексте регулярных
выражений - они означают <любой символ из перечисленных в скобках>. В
отличие от регулярного выражения php, которое совпадает во всех строках,
содержащих литеральный текст php, выражение [php] совпадает в любой
строке, содержащей символы р или h. Квадратные скобки играют важную роль
при работе с регулярными выражениями, поскольку в процессе поиска часто
возникает задача поиска символов из заданного интервала. Ниже перечислены
некоторые часто используемые интервалы:
- [0-9] - совпадает с любой десятичной цифрой от 0 до 9;
- [a-z] - совпадает с любым символом нижнего регистра от а до z;
- [A-Z] - совпадает с любым символом верхнего регистра от А до Z;
- [a -Z] - совпадает с любым символом нижнего или верхнего регистра от
а до Z.
Конечно, перечисленные выше интервалы всего лишь демонстрируют общий
принцип. Например, вы можете воспользоваться интервалом [0-3] для
обозначения любой десятичной цифры от 0 до 3 или интервалом [b-v] для
обозначения любого символа нижнего регистра от b до v. Короче говоря,
интервалы определяются совершенно произвольно.
Квантификаторы
Существует особый класс служебных символов, обозначающих количество
повторений отдельного символа или конструкции, заключенной в квадратные
скобки. Эти служебные символы (+, * и {...}) называются квантификаторами.
Принцип их действия проще всего пояснить на примерах:
- р+ означает один или несколько символов р, стоящих подряд;
- р* означает ноль и более символов р, стоящих подряд;
- р? означает ноль или один символ р;
- р{2} означает два символа р, стоящих подряд;
- р{2,3} означает от двух до трех символов р, стоящих подряд;
- р{2,} означает два и более символов р, стоящих подряд.
Прочие служебные символы
Служебные символы $ и ^ совпадают не с символами, а с определенными
позициями в строке. Например, выражение р$ означает строку, которая
завершается символом р, а выражение ^р - строку, начинающуюся с символа
р.
- Конструкция [^a-zA-Z] совпадает с любым символом, не входящим в
указаные интервалы (a-z и A-Z).
- Служебный символ . (точка) означает <любой символ>. Например,
выражение р.р совпадает с символом р, за которым следует произвольный
символ, после чего опять следует символ р.
Объединение служебных символов приводит к появлению более сложных
выражений. Рассмотрим несколько примеров:
- ^.{2}$ - любая строка, содержащая ровно два символа;
- <b>(.*)</b> - произвольная последовательность символов,
заключенная между <Ь> и </Ь> (вероятно, тегами HTML для
вывода жирного текста);
- p(hp)* - символ р, за которым следует ноль и более экземпляров
последовательности hp (например, phphphp).
Иногда требуется найти служебные символы в строках вместо того, чтобы
использовать их в описанном специальном контексте. Для этого служебные
символы экранируются обратной косой чертой (\). Например, для поиска
денежной суммы в долларах можно воспользоваться выражением \$[0-9]+, то
есть <знак доллара, за которым следует одна или несколько десятичных
цифр>. Обратите внимание на обратную косую черту перед $. Возможными
совпадениями для этого регулярного выражения являются $42, $560 и $3.
Стандартные интервальные выражения (символьные классы)
Для удобства программирования в стандарте POSIX были определены
некоторые стандартные интервальные выражения, также называемые символьными
классами (character classes). Символьный класс определяет один символ из
заданного интервала - например, букву алфавита или цифру:
- [[:alpha:]] - алфавитный символ (aA-zZ);
- [[:digit:]]-цифра (0-9);
- [[:alnum:]] - алфавитный символ (aA-zZ) или цифра (0-9);
- [[:space:]] - пропуски (символы новой строки, табуляции и т. д.).
Функции РНР для работы с регулярными выражениями
(POSIX-совместимые)
В настоящее время РНР поддерживает семь функций поиска с использованием
регулярных выражений в стиле POSIX:
- еrеg( );
- еrеg_rерlасе( );
- eregi( );
- eregi_replace( );
- split( );
- spliti( );
- sql_regcase( ).
Описания этих функций приведены в следующих разделах.
ereg( )
Функция еrеg( ) ищет в заданной строке совпадение для шаблона. Если
совпадение найдено, возвращается TRUE, в противном случае возвращается
FALSE. Синтаксис функции ereg( ):
int ereg (string шаблон, string строка [, array совпадения])
Поиск производится с учетом регистра алфавитных символов. Пример
использования ereg( ) для поиска в строках доменов .соm:
$is_com - ereg("(\.)(com$)", $email):
// Функция возвращает TRUE, если $email завершается символами
".com"
// В частности, поиск будет успешным для строк
// "www.wjgilmore.com" и "someemail@apress.com"
Обратите внимание: из-за присутствия служебного символа $ регулярное
выражение совпадает только в том случае, если строка завершается символами
.com. Например, оно совпадет в строке "www.apress.com", но не совпадет в
строке "www.apress.com/catalog".
Необязательный параметр совпадения содержит массив совпадений для всех
подвыражений, заключенных в регулярном выражении в круглые скобки. В
листинге 8.1 показано, как при помощи этого массива разделить URL на
несколько сегментов.
Листинг 8.1. Вывод элементов массива $regs
$url = "http://www.apress.com";
// Разделить $url на три компонента: "http://www". "apress" и "com"
$www_url = ereg("^(http://www)\.([[:alnum:]+\.([[:alnum:]]+)". $url,
$regs);
if ($www_url) : // Если переменная $www_url содержит URL
echo $regs[0]; // Вся строка "http://www.apress.com"
print "<br>";
echo $regs[l]; // "http://www"
print "<br>";
echo $regs[2]; // "apress"
print "<br>";
echo $regs[3]; // "com" endif;
При выполнении сценария в листинге 8.1 будет получен следующий
результат:
http://www.apress.com http://www apress com
ereg_replace( )
Функция ereg_replace( ) ищет в заданной строке совпадение для шаблона и
заменяет его новым фрагментом. Синтаксис функции ereg_replace( ):
string ereg_replace (string шаблон, string замена, string строке)
Функция ereg_replace( ) работает по тому же принципу, что и ereg( ), но
ее возможности расширены от простого поиска до поиска с заменой. После
выполнения замены функция возвращает модифицированную строку. Если
совпадения
отсутствуют, строка остается в прежнем состоянии. Функция ereg_replace(
), как и еrеg( ), учитывает регистр символов. Ниже приведен простой
пример, демонстрирующий применение этой функции:
$copy_date = "Copyright 1999":
$copy_date = ereg_replace("([0-9]+)". "2000", $copy_date);
print $copy_date: // Выводится строка "Copyright 2000"
У средств поиска с заменой в языке РНР имеется одна интересная
возможность - возможность использования обратных ссылок на части основного
выражения, заключенные в круглые скобки. Обратные ссылки похожи на
элементы необязательного параметра-массива совпадения функции еrеg( ) за
одним исключением: обратные ссылки записываются в виде \0, \1, \2 и т. д.,
где \0 соответствует всей строке, \1 - успешному совпадению первого
подвыражения и т. д. Выражение может содержать до 9 обратных ссылок. В
следующем примере все ссылки на URL в тексте заменяются работающими
гиперссылками:
$url = "Apress (http://www.apress.com");
$url = ereg_replace("http://(([A-Za-z0-9.\-])*)", "<a
href=\"\\0\">\\0</a>", $url);
print $url;
// Выводится строка:
// Apress (<a
href="http://www.apress.com">http://www.apress.com</a>)
eregi( )
Функция eregi( ) ищет в заданной строке совпадение для шаблона.
Синтаксис функции eregi( ):
int eregi (string шаблон, string строка [, array совпадения])
Поиск производится без учета регистра алфавитных символов. Функция
eregi( ) особенно удобна при проверке правильности введенных строк
(например, паролей). Использование функции eregi( ) продемонстрировано в
следующем примере:
$password = "abc";
if (! eregi("[[:alnum:]]{8.10}, $password) :
print "Invalid password! Passwords must be from 8 through 10 characters
in length.";
endif;
// В результате выполнения этого фрагмента выводится сообщение об
ошибке.
// поскольку длина строки "abc" не входит в разрешенный интервал
// от 8 до 10 символов.
eregi_replace( )
Функция eregi_replасе( ) работает точно так же, как ereg_replace( ), за
одним исключением: поиск производится без учета регистра символов.
Синтаксис функции ereg_replace( ):
string eregi_replace (string шаблон, string замена, string строка)
split( )
Функция split( ) разбивает строку на элементы, границы которых
определяются по заданному шаблону. Синтаксис функции split( ):
array split (string шаблон, string строка [, int порог])
Необязательный параметр порог определяет максимальное количество
элементов, на которые делится строка слева направо. Если шаблон содержит
алфавитные символы, функция spl it( ) работает с учетом регистра символов.
Следующий пример демонстрирует использование функции split( ) для
разбиения канонического IP-адреса на триплеты:
$ip = "123.345.789.000"; // Канонический IP-адрес
$iparr = split ("\.", $ip) // Поскольку точка является служебным
символом.
// ее необходимо экранировать.
print "$iparr[0] <br>"; // Выводит "123"
print "$iparr[1] <br>"; // Выводит "456"
print "$iparr[2] <br>"; // Выводит "789"
print "$iparr[3] <br>"; // Выводит "000"
spliti( )
Функция spliti( ) работает точно так же, как ее прототип split( ), за
одним исключением: она не учитывает регистра символов. Синтаксис функции
spliti( ):
array spliti (string шаблон, string строка [, int порог])
Разумеется, регистр символов важен лишь в том случае, если шаблон
содержит алфавитные символы. Для других символов выполнение spliti( )
полностью аналогично split( ).
sql_regcase( )
Вспомогательная функция sql_regcase( ) заключает каждый символ входной
строки в квадратные скобки и добавляет к нему парный символ. Синтаксис
функции sql_regcase( ):
string sql_regcase (string строка)
Если алфавитный символ существует в двух вариантах (верхний и нижний
регистры), выражение в квадратных скобках будет содержать оба варианта; в
противном случае исходный символ повторяется дважды. Функция sql_regcase(
) особенно удобна при использовании РНР с программными пакетами,
поддерживающими регулярные выражения в одном регистре. Пример
преобразования строки функцией sql_regcase( ):
$version = "php 4.0";
print sql_regcase($version);
// Выводится строка [Pp][Hh][Pp][ ][44][..][00]
Синтаксис регулярных выражений в стиле Perl
Perl (http://www.perl.com/) давно
считается одним из самых лучших языков обработки текстов. Синтаксис Perl
позволяет осуществлять поиск и замену даже для самых сложных шаблонов.
Разработчики РHР сочли, что не стоит заново изобретать уже изобретенное, а
лучше сделать знаменитый синтаксис регулярных выражений Perl доступным для
пользователей РНР. Так появились функции для работы с регулярными
выражениями в стиле Perl.
Диалект регулярных выражений Perl не так уж сильно отличается от
диалекта POSIX. В сущности, синтаксис регулярных выражений Perl является
отдаленным потомком реализации POSIX, вследствие чего синтаксис POSIX
почти совместим с функциями регулярных выражений стиля Perl.
Оставшаяся часть этого раздела будет посвящена краткому знакомству с
диалектом регулярных выражений Perl. Рассмотрим простой пример:
/food/
Обратите внимание: строка food заключена между двумя косыми чертами.
Как и в стандарте POSIX, вы можете создавать более сложные шаблоны при
помощи квантификаторов:
/fo+/
Этот шаблон совпадает с последовательностью fo, за которой могут
следовать дополнительные символы о. Например, совпадения будут обнаружены
в строках food, fool и fo4. Рассмотрим другой пример использования
квантификатора:
/fo{2,4}/
Шаблон совпадает с символом f, за которым следуют от 2 до 4 экземпляров
символа о. К числу потенциальных совпадений относятся строки fool , fooool
и foosball .
В регулярных выражениях Perl могут использоваться все квантификаторы,
упомянутые в предыдущем разделе для регулярных выражений POSIX.
Метасимволы
Одной из интересных особенностей Perl является использование
метасимволов при поиске. Метасимвол [Следует отметить, что авторское
толкование термина <метасимвол> противоречит не только всем традициям, по
и официальной документации РНР. - Примеч. перев.] представляет собой
алфавитный символ с префиксом \ - признаком особой интерпретации
следующего символа. Например, метасимвол \d может использоваться при
поиске денежных сумм:
/([d]+)000/
Комбинация \d обозначает любую цифру. Конечно, в процессе поиска часто
возникает задача идентификации алфавитно-цифровых символов, поэтому в Perl
для них был определен метасимвол \w:
/<([\w]+)>/
Этот шаблон совпадает с конструкциями, заключенными в угловые скобки, -
например, тёгами HTML. Кстати, метасимвол \W имеет прямо противоположный
смысл и используется для идентификации символов, не являющихся
алфавитно-цифровыми.
Еще один полезный метасимвол, \b, совпадает с границами слов:
/sa\b/
Поскольку метасимвол границы слова расположен справа от текста, этот
шаблон совпадет в строках salsa и lisa, но не в строке sand.
Противоположный метасимвол, \В, совпадает с чем угодно, кроме границы
слова:
/sa\B/
Шаблон совпадает в таких строках, как sand и Sally, но не совпадает в
строке salsa.
Модификаторы
Модификаторы заметно упрощают работу с регулярными выражениями.
Впрочем, модификаторов много, и в табл. 8.1 приведены лишь наиболее
интересные из них. Модификаторы перечисляются сразу же после регулярного
выражения - например, /string/i.
Таблица 8.1. Примеры модификаторов
Модификатор |
Описание |
m |
Фрагмент текста интерпретируется как состоящий из
нескольких <логических строк>. По умолчанию специальные символы ^ и
$ совпадают только в начале и в конце всего фрагмента. При включении
<многострочного режима> при помощи модификатора m^ и $ будут
совпадать в начале и в конце каждой логической строки внутри
фрагмента |
s |
По смыслу противоположен модификатору m - при поиске
фрагмент интерпретируется как одна строка, а все внутренние символы
новой строки игнорируются |
i |
Поиск выполняется без учета регистра
символов |
Вводный курс получился очень кратким, поскольку полноценное описание по
регулярным выражениям выходит за рамки этой книги и требует нескольких
глав вместо нескольких страниц. За дополнительной информацией о синтаксисе
регулярных выражений обращайтесь к следующим ресурсам Интернета:
Функции РНР для работы
с регулярными выражениями (Perl-совместимые)
В РНР существует пять функций поиска по шаблону с использованием
Perl-совместимых регулярных выражений:
- preg_match( );
- preg_match_all( );
- preg_replace( );
- preg_split( );
- preg_grep( ).
Эти функции подробно описаны в следующих разделах.
preg_match( )
Функция pregjnatch( ) ищет в заданной строке совпадение для шаблона.
Если совпадение найдено, возвращается TRUE, в противном случае
возвращается FALSE. Синтаксис функции pregjnatch( ):
int pregjnatch (string шаблон, string строка [, array совпадения})
При передаче необязательного параметра совпадения массив заполняется
совпадениями различных подвыражений, входящих в основное регулярное
выражение. В следующем примере функция preg_match( ) используется для
проведения поиска без учета регистра:
$linе = "Vi is the greatest word processor ever created!";
// Выполнить поиск слова "Vi" без учета регистра символов:
if (preg_match("/\bVi\b\i", $line, $matcn)) :
print "Match found!";
endif;
// Команда if в этом примере возвращает TRUE
preg_match_all( )
Функция preg_match_all( ) находит все совпадения шаблона в заданной
строке.
Синтаксис функции preg_match_all( ):
Int preg_match_all (string шаблон, string строка, array совпадения [,
int порядок])
Порядок сохранения в массиве совпадения текста, совпавшего с
подвыражениями, определяется необязательным параметром порядок. Этот
параметр может принимать два значения:
- PREG_PATTERN_ORDER - используется по умолчанию, если параметр
порядок не указан. Порядок, определяемый значением PREG_PATTERN_ORDER,
на первый взгляд выглядит не совсем логично: первый элемент (с индексом
0) содержит массив совпадений для всего регулярного выражения, второй
элемент (с индексом 1) содержит массив всех совпадений для первого
подвыражения в круглых скобках и т. д.;
- PREG_SET_ORDER - порядок сортировки массива несколько отличается от
принятого по умолчанию. Первый элемент (с индексом 0) содержит массив с
текстом, совпавшим со всеми подвыражениями в круглых скобках для первого
найденного совпадения. Второй элемент (с индексом 1) содержит
аналогичный массив для второго найденного совпадения и т. д.
Следующий пример показывает, как при помощи функции preg_match_al( )
найти весь текст, заключенный между тегами HTML
<b>...</b>:
$user_info = "Name: <b>Rasmus Lerdorf</b> <br> Title:
<b>PHP Guru</b>";
preg_match_all ("/<b>(.*)<\/b>/U", Suserinfo.
$pat_array);
print $pat_array[0][0]." <br> ".pat_array[0][l]."\n":
Результат:
Rasmus Lerdorf
PHP Guru
preg_replace( )
Функция preg_repl ace( ) работает точно так же, как и ereg_replасе( ),
за одним исключением - регулярные выражения могут использоваться в обоих
параметрах, шаблон и замена. Синтаксис функции preg_replace( ):
mixed preg_replace (mixed шаблон, mixed замена, mixed строка [, int
порог])
Необязательный параметр порог определяет максимальное количество замен
в строке. Интересный факт: параметры шаблон и замена могут представлять
собой масивы. Функция preg_replace( ) перебирает элементы обоих массивов и
выполняет замену по мере их нахождения.
preg_split( )
Функция preg_spl it( ) аналогична split( ) за одним исключением -
параметр шаблон может содержать регулярное выражение. Синтаксис функции
preg_split( ):
array preg_split (string шаблон, string строка [, int порог [, int
флаги]])
Необязательный параметр порог определяет максимальное количество
элементов, на которые делится строка. В следующем примере функция
preg_split( ) используется для выборки информации из переменной.
$user_info="+wj+++Gilmore+++++wjgi]more@hotmail.com
+++++++Columbus+++OH";
$fields = preg_split("/\+{1.}/", $user_info);
while ($x < sizeof($fields)):
print $fields[$x]. "<br>";
$x++;
endwhile;
Результат:
WJ
Gilmore
wjgilmore@hotmail.com
Columbus
OH
preg_grep( )
Функция preg_grep( ) перебирает все элементы заданного массива и
возвращает все элементы, в которых совпадает заданное регулярное
выражение. Синтаксис функции preg_grep():
array preg_grep (string шаблон, array массив)
Пример использования функции preg_grep( ) для поиска в массиве слов,
начинающихся на р:
$foods = array ("pasta", "steak", "fish", "potatoes");
// Поиск элементов, начинающихся с символа "р".
// за которым следует один или несколько символов
$p_foods = preg_grep("/p(\w+)/", $foods):
$х = 0;
while ($x < sizeof($p_foods)) :
print $p_foods[$x]. "<br>";
$Х++;
endwhile;
Результат:
pasta
potatoes
Другие строковые функции
Кроме функций для работы с регулярными выражениями, описанными в первой
части этой главы, в РНР существует более 70 функций для выполнения
практически всех мыслимых операций со строками. Подробное перечисление и
описание всех функций выходит за рамки этой книги и приведет к обычному
повторению информации, приведенной в документации РНР. По этой причине я
превратил оставшуюся часть главы в своего рода список FAQ из вопросов,
часто встречающихся во многих электронных конференциях РНР и на многих
сайтах этой тематики. На мой взгляд, этот способ позволяет гораздо
эффективнее описать общие принципы громадной библиотеки строковых функций
РНР.
Дополнение и сжатие строк
В процессе форматирования часто возникает необходимость в изменении
длины строки посредством дополнения или удаления символов. В РНР
существует несколько функций, предназначенных для решения этой задачи.
chop ( )
Функция chop( ) возвращает строку после удаления из нее завершающих
пропусков и символов новой строки. Синтаксис функции chop( ):
string chop(string строка)
В следующем примере функция chop( ) удаляет лишние символы новой
строки:
$header = "Table of Contents\n\n";
$header = chop($header);
// $header = "Table of Contents"
str_pad( )
Функция str_pad( ) выравнивает строку до определенной длины заданными
символами и возвращает отформатированную строку. Синтаксис функции
str_pad( ):
string str_pad (string строка, int длина_дополнения [, string
дополнение [, int тип_дополнения]])
Если необязательный параметр дополнение не указан, строка дополняется
пробелами. В противном случае строка дополняется заданными символами. По
умолчанию строка дополняется справа; тем не менее, вы можете передать в
параметре тип_дополнения константу STR_PAD_RIGHT, STR_PAD_LEFT или
STR_PAD_BOTH, что приведет к дополнению строки в заданном направлении.
Пример демонстрирует дополнение строки функцией str_pad( ) с параметрами
по умолчанию:
$food = "salad";
print str_pad ($food, 5): // Выводит строку "salad
В следующем примере используются необязательные параметры функции
str_pad( ):
$header = "Table of Contents";
print str_pad ($header, 5, "=+=+=", STR_PAD_BOTH);
// В браузере выводится строка =+=+= Таbе of Contents=+=+="
trim ( )
Функция trim( ) удаляет псе пропуски с обоих краев строки и возвращает
полученную строку. Синтаксис функции trim( ):
string trim (string страна]
К числу удаляемых пропусков относятся и специальные символы \n, \r, \t,
\v и \0.
ltrim( )
Функция lrim( ) удаляет все пропуски и специальные символы с левого
края строки и возвращает полученную строку. Синтаксис функции ltrim(
):
string ltrim (string строка)
Функция удаляет те же специальные символы, что и функция trim( ).
Определение длины строки
Длину строки в символах можно определить при помощи функции strlen( ).
Синтаксис .функции strlen( ):
int strlen (string строка)
Следующий пример демонстрирует определение длины строки функцией
strlen( ):
$string = "hello";
$length = strlen($string);
// $length = 5
Сравнение двух строк
Сравнение двух строк принадлежит к числу важнейших строковых операций
любого языка. Хотя эту задачу можно решить несколькими разными способами,
в РНР существуют четыре функции сравнения строк:
- strcmp( );
- strcasecmp( );
- strspn( );
- strcspn( ).
Все эти функции подробно описаны в следующих разделах.
strcmp( )
Функция strcmp( ) сравнивает две строки с учетом регистра символов.
Синтаксис функции strcmp( ):
int strcmp (string строка1, string строка2)
После завершения сравнения strcmp( ) возвращает одно из трех возможных
значений:
- 0, если строка1 и строка2 совпадают;
- < 0, если строка1 меньше, чем строка2;
- > 0, если строка2 меньше, чем строка1.
В следующем фрагменте сравниваются две одинаковые строки:
$sthng1 = "butter";
$string2 = "butter";
if ((strcmp($string1. $string2)) == 0) :
print "Strings are equivalent!"; endif;
// Команда if возвращает TRUE
strcasecmp( )
Функция strcasecmp( ) работает точно так же, как strcmp( ), за одним
исключением - регистр символов при сравнении не учитывается. Синтаксис
функции strcasecmp( ):
int strcasecmp (string cтpoкa1, string строка2)
В следующем фрагменте сравниваются две одинаковые строки:
$string1 = "butter";
$string2 = "Butter";
if ((strcmp($string1, $string2)) == 0) :
print "Strings are equivalent!";
endif;
// Команда if возвращает TRUE
strspn( )
Функция strspn( ) возвращает длину первого сегмента строки1,
содержащего символы, присутствующие в строке2. Синтаксис функции strspn(
):
int strspn (string строка1, string строка2)
Следующий фрагмент показывает, как функция strspn( ) используется для
проверки пароля:
$password = "12345";
if (strspn($password, "1234567890") != strlen($password)) :
print "Password cannot consist solely of numbers!";
endif:
strcspn( )
Функция strcspn( ) возвращает длину первого сегмента строки1,
содержащего символы, отсутствующие в строке2. Синтаксис функции strcspn(
):
int strcspn (string строка1, string строка2)
В следующем фрагменте функция strcspn( ) используется для проверки
пароля:
$password = "12345";
if (strcspn($password, "1234567890") == 0) :
print "Password cannot consist solely of numbers!";
endif;
Обработка строковых данных без применения регулярных
выражений
При обработке больших объемов информации функции регулярных выражений
сильно замедляют выполнение программы. Эти функции следует применять лишь
при обработке относительно сложных строк, в которых регулярные выражения
действительно необходимы. Если же анализ текста выполняется по
относительно простым правилам, можно воспользоваться стандартными
функциями РНР, которые заметно ускоряют обработку. Все эти функции описаны
ниже.
strtok( )
Функция strtok( ) разбивает строку на лексемы по разделителям, заданным
вторым параметром. Синтаксис функции strtok( ):
string strtok (string строка, string разделители)
У функции strtok( ) есть одна странность: чтобы полностью разделить
строку, функцию необходимо последовательно вызвать несколько раз. При
очередном вызове функция выделяет из строки следующую лексему. При этом
параметр строка задается всего один раз - функция отслеживает текущую
позицию в строке до тех пор, пока строка не будет полностью разобрана на
лексемы или не будет задан новый параметр строка. Следующий пример
демонстрирует разбиение строки по нескольким разделителям:
$info = "WJ Gi1more:wjgilmore@hotmail.com | Columbus, Ohio";
// Ограничители - двоеточие (:), вертикальная черта (|) и запятая (.)
$tokens = ":|,";
$tokenized = strtok($info, $tokens);
// Вывести элементы массива $tokenized
while ($tokenized) :
echo "Element = $tokenized<br>";
// Обратите внимание: при последующих вызовах strtok
// первый аргумент не передается
$tokenized = strtok($tokens);
endwhile;
Результат:
Element = WJGilmore
Element = wjgilmore@hotmail.com
Element = Columbus
Element = Ohio
parse_str( )
Функция parse_str( ) выделяет в строке пары <переменная-значение> и
присваивает значения переменных в текущей области видимости. Синтаксис
функции parse_str( ):
void parse_str (string строка)
Функция parse_str( ) особенно удобна при обработке URL, содержащих
данные форм HTML или другую расширенную информацию. В следующем примере
анализируется информация, переданная через URL. Строка представляет собой
стандартный способ передачи данных между страницами либо откомпилированных
в гиперссылке, либо введенных в форму HTML:
$url = "fname=wj&lname=gilmore&zip=43210";
parse_str($url);
// После выполнения parse_str( ) доступны следующие переменные:
// $fname = "wj":
// $lname = "gilmore";
// $zip = "43210"
Поскольку эта функция создавалась для работы с URL, она игнорирует
символ амперсанд (&).
Работа с формами HTML в РНР
описана в главе 10.
explode ( )
Функция explode( ) делит строку на элементы и возвращает эти элементы в
виде массива. Синтаксис функции explode( ):
array explode (string разделитель, string строка [, int порог])
Разбиение происходит по каждому экземпляру разделителя, причем
количество полученных фрагментов может ограничиваться необязательным
параметром порог. Разделение строки функцией explode( ) продемонстрировано
в следующем примере:
$info = "wilson | baseball | indians";
$user = explode("|", $info);
// $user[0] = "wilson";
// $user[1] = "baseball";
// $user[2] = "Indians";
Функция explode( ) практически
идентична функции регулярных выражений POSIX split( ), описанной выше.
Главное различие заключается в том, что передача регулярных выражений в
параметрах допускается только при вызове split( ).
implode ( )
Если функция explode( ) разделяет строку на элементы массива, то ее
двойник - функция implode( ) - объединяет массив в строку. Синтаксис
функции implode( ):
string implode (string разделитель, array фрагменты)
Формирование строки из массива продемонстрировано в следующем
примере:
$ohio_cities = array ("Columbus", "Youngstown", "Cleveland",
"Cincinnati");
$city_string = implode("l", $ohio_cities);
// $city_string = "Columbus | Youngstown | Cleveland | Cincinnati";
У implode( ) имеется псевдоним
- функция join( ).
strpos ( )
Функция strpos( ) находит в строке первый экземпляр заданной подстроки.
Синтаксис функции strpos( ):
int strpos (string строка, string подстрока [, int смещение])
Необязательный параметр offset задает позицию, с которой должен
начинаться поиск. Если подстрока не найдена, strpos( ) возвращает FALSE
(0).
В следующем примере определяется позиция первого вхождения даты в файл
журнала:
$log = "
206.169.23.11:/www/:2000-08-10
206.169.23.11:/www/logs/:2000-02-04
206.169.23.11:/www/img/:1999-01-31";
// В какой позиции в журнале впервые встречается 1999 год?
$pos = strpos($log, "1999");
// $pos = 95. поскольку первый экземпляр "1999"
// находится в позиции 95 строки, содержащейся в переменной $log
strrpos( )
Функция strrpos( ) находит в строке последний экземпляр заданного
символа. Синтаксис функции strrpos( ):
int strpos (string строка, char символ)
По возможностям эта функция уступает своему двойнику - функции strpos(
), поскольку она позволяет искать только отдельный символ, а не всю
строку. Если во втором параметре strrpos( ) передается строка, при поиске
будет использован только ее первый символ.
str_replace( )
Функция str_replace( ) ищет в строке все вхождения заданной подстроки и
заменяет их новой подстрокой. Синтаксис функции str_replace( ):
string str_replace (string подстрока, string замена, string строка)
Функция substr_replace( ),
описанная ниже в этом разделе, позволяет провести заме ну лишь в
определенной части строки. Ниже показано, как функция str_replace( )
используется для проведения глобальной замены в строке.
Если подстрока ни разу не встречается в строке, исходная строка не
изменяется:
$favorite_food = "My favorite foods are ice cream and chicken
wings";
$favorite_food = str_replace("chicken_wings", "pizza",
$favohte_food);
// $favorite_food = "My favorite foods are ice cream and pizza"
strstr( )
Функция strstr( ) возвращает часть строки, начинающуюся с первого
вхождения заданной подстроки. Синтаксис функции strstr( ):
string strstr (string строка, string подстрока)
В следующем примере функция strstr( ) используется для выделения имени
домена из URL:
$url = "http://www.apress.com"; $domain - strstr($url, ".");
// $domain = ".apress.com"
substr( )
Функция substr( ) возвращает часть строки, начинающуюся с заданной
начальной позиции и имеющую заданную длину. Синтаксис функции substr(
):
string substr (string строка, int начало [, int длина])
Если необязательный параметр длина не указан, считается, что подстрока
начинается с заданной начальной позиции и продолжается до конца строки.
При использовании этой функции необходимо учитывать четыре
обстоятельства:
- если параметр начало положителен, возвращаемая подстрока начинается
с позиции строки с заданным номером;
- если параметр начало отрицателен, возвращаемая подстрока начинается
с позиции (длина строки - начало);
- если параметр длина положителен, в возвращаемую подстроку включаются
все символы от позиции начало до позиции начало+длина. Если последняя
величина превышает длину строки, возвращаются символы до конца строки;
- если параметр длина отрицателен, возвращаемая подстрока
заканчивается на заданном расстоянии от конца строки.
Помните о том, что параметр
начало определяет смещение от первого символа строки; таким образом,
возвращаемая строка в действительности начинается с символа с номером
(начало + 1).
Следующий пример демонстрирует выделение части строки функцией substr(
):
$car = "1944 Ford"; Smodel = substr($car, 6);
// Smodel = "Ford"
Пример с положительным параметром длина:
$car = "1944 Ford";
$model = substr($car, 0, 4);
// $model = "1944"
Пример с отрицательным параметром длина:
$car = "1944 Ford";
$model = substr($car, 2, -5);
// $model = "44"
substr_count( )
Функция substr_count( ) возвращает количество вхождений подстроки в
заданную строку. Синтаксис функции substr_count( ):
int substr_count (string строка, string подстрока)
В следующем примере функция substr_count( ) подсчитывает количество
вхождений подстроки ain:
$tng_twist = "The rain falls mainly on the plains of Spain";
$count = substr_count($tng_twist, "ain");
// $count = 4
substr_replace( )
Функция substr_replace( ) заменяет часть строки, которая начинается с
заданной позиции. Если задан необязательный параметр длина, заменяется
фрагмент заданной длины; в противном случае производится замена по всей
длине заменяющей строки. Синтаксис функции substr_replace( ):
string substr_replace (string строка, string замена, int начало [, int
длина])
Параметры начало и длина задаются по определенным правилам:
- если параметр начало положителен, замена начинается с заданной
позиции;
- если параметр начало отрицателен, замена начинается с позиции (длина
строки -начало);
- если параметр длина положителен, заменяется фрагмент заданной длины;
- если параметр длина отрицателен, замена завершается в позиции (длина
строки -длина).
Простая замена текста функцией substr_replace( ) продемонстрирована в
следующем примере:
$favs = " 's favorite links";
$name = "Alessia";
// Параметры "0, 0" означают, что заменяемый фрагмент начинается
// и завершается в первой позиции строки.
$favs - substr_replace($favs, $name, 0, 0);
print $favs:
Результат:
Alessia's favorite links
Преобразование строк и файлов к формату HTML и
наоборот
Преобразовать строку или целый файл к формату, подходящему для
просмотра в web-браузере (или наоборот), проще, чем может показаться на
первый взгляд. В РНР для этого существуют специальные функции.
Преобразование текста в HTML
Быстрое преобразование простого текста к формату web-браузера - весьма
распространенная задача. В ее решении вам помогут функции, описанные в
этом разделе.
nl2br( )
Функция nl2br( ) заменяет все символы новой строки (\n) эквивалентными
конструкциями HTML <br>.
Синтаксис функции nl2br( ):
string nl2br (string строка)
Символы новой строки могут быть как видимыми (то есть явно включенными
в строку), так и невидимыми (например, введенными в редакторе). В
следующем примере текстовая строка преобразуется в формат HTML посредством
замены символов \n разрывами строк:
// Текстовая строка, отображаемая в редакторе.
$text_recipe = "
Party Sauce recipe:
1 can stewed tomatoes
3 tablespoons fresh lemon juice
Stir together, server cold.";
// Преобразовать символы новой строки в <br>
$htinl_recipe = nl2br($text_recipe)
При последующем выводе $html_recipe браузеру будет передан следующий
текст в формате HTML:
Party Sauce recipe:<br>
1 can stewed tomatoes<br>
3 tablespoons fresh lemon juice<br>
Stir together, server cold.<br>
htmlentities( )
Функция htmlentities( ) преобразует символы в эквивалентные конструкции
HTML. Синтаксис функции htmlentities:
string htmlentities (string строка)
В следующем примере производится необходимая замена символов строки для
вывода в браузере:
$user_input = "The cookbook, entitled Cafe Francaise' costs <
$42.25.";
$converted_input = htmlentities($user_input);
// $converted_input = "The cookbook, entitled 'Cafè
// Fracçiaise' costs < 42.25.";
Функция htmlentities( ) в
настоящее время работает только для символов кодировки ISO-8559-1
(ISO-Latin-1). Кроме того, она не преобразует пробелы в , как
следовало бы ожидать.
htmlspecialchars( )
Функция htmlspecialchars( ) заменяет некоторые символы, имеющие особый
смысл в контексте HTML, эквивалентными конструкциями HTML. Синтаксис
функции htmlspecialchars( ):
string htmlspecialchars (string строка)
Функция html special chars( ) в настоящее время преобразует следующие
символы:
& преобразуется в &; " " преобразуется в ";
< преобразуется в <; > преобразуется в >.
В частности, эта функция позволяет предотвратить ввод пользователями
разметки HTML в интерактивных web-приложениях (например, в электронных
форумах). Ошибки, допущенные в разметке HTML, могут привести к тому, что
вся страница будет формироваться неправильно. Впрочем, у этой задачи
существует и более эффективное решение - полностью удалить теги из строки
функцией strip_tags( ).
Следующий пример демонстрирует удаление потенциально опасных символов
функцией htmlspeclalchars( ):
$user_input = "I just can't get of PHP & those fabulous
cooking recipes!";
$conv_input = htmlspecialchars($user_input);
// $conv_input = "I just can't <<enough>>
of PHP & those fabulous cooking
recipes!"
Если функция htmlspecialchars(
) используется в сочетании с nl2br( ), то последнюю следует вызывать после
htmlspecialchars( ). В противном случае конструкции <br>,
сгенерированные при вызове nl2br( ), преобразуются в видимые символы.
get_html_translation_table ( )
Функция get_html_translation_table( ) обеспечивает удобные средства
преобразования текста в эквиваленты HTML Синтаксис функции
get_htrril_translation_table( ):
string get_html_translation_table (int таблица)
Функция get_html_translation_table( ) возвращает одну из двух таблиц
преобразования (определяется параметром таблица), используемых в работе
стандартных функций htmlspecialchars( ) и htmlentities( ). Возвращаемое
значение может использоваться в сочетании с другой стандартной функцией,
strtr( ) (см. далее), для преобразования текста в код HTML.
Параметр таблица принимает одно из двух значений:
- HTML_ENTITIES;
- HTML_SPECIALCHARS.
В следующем примере функция get_html_translation_table( ) используется
при преобразовании текста в код HTML:
$string = "La pasta e il piatto piu amato in Italia";
$translate = get_html_translation_table(HTML_ENTITIES);
print strtr($string, $translate);
// Специальные символы преобразуются в конструкции HTML
// и правильно отображаются в браузере.
Кстати, функция array_flip( ) позволяет провести преобразование текста
в HTML в обратном направлении и восстановить исходный текст. Предположим,
что вместо вывода результата strtr( ) в предыдущем примере мы присвоили
его переменной $translated string.
В следующем примере исходный текст восстанавливается функцией
array_flip( ):
$translate = array_flip($translate);
$translated_string - "La pasta é il piatto piú
amato in Italia";
$original_string = strtr($translated_string, $translate);
// $original_string = "La pasta e il piatto piu amato in Italia";
strtr( )
Функция strtr( ) транслирует строку, то есть заменяет в ней все
символы, входящие в строку источник, соответствующими символами строки
приемник. Синтаксис функции strtr( ):
string strtr (string строка, string источник, string приемник)
Если строки источник и приемник имеют разную длину, длинная строка
усекается до размеров короткой строки.
Существует альтернативный синтаксис вызова strtr( ) с двумя
параметрами; в этом случае второй параметр содержит ассоциативный массив,
ключи которого соответствуют заменяемым подстрокам, а значения -
заменяющим подстрокам. В следующем примере теги HTML заменяются
XML-подобными конструкциями:
$source = array("<title>" => "<h1>". "</title>
=> "</h1>");
$string = "<h1>Today In PHP-Powered News"</h1>";
print strtr($string, $source);
// Выводится строка "<title>Today in PHP-Powered
News</title>"
Преобразование HTML
в простой текст
Иногда возникает необходимость преобразовать файл в формате HTML в
простой текст. Функции, описанные ниже, помогут вам в решении этой
задачи.
strip_tags( )
Функция strip_tags( ) удаляет из строки все теги HTML и РНР, оставляя в
ней только текст. Синтаксис функции strip_tags( ):
string strip_tags (string строка [, string разрешенные_тerи])
Необязательный параметр разрешенные_теги позволяет указать теги,
которые должны пропускаться в процессе удаления.
Ниже приведен пример удаления из строки всех тегов HTML функцией
strip_tags( ):
$user_input = "I just <b>love</b> РНР and
<i>gourment</i> recipes!";
$stripped_input = strip_tags($user_input);
// $stripped_input = "I just love PHP and gourmet recipes!";
В следующем примере удаляются не все, а лишь некоторые теги:
$input = "I <b>love</b> to <a href =
\"http://www.eating.com\">eat!</a>!";
$strip_input = strip_tags ($user_input, "<a>");
// $strip_input = "I love to <a href =
\"http://www.eating.com\">eat!</a>!";
Удаление тегов из текста также
производится функцией fgetss( ), описанной в главе 7.
get_meta_tags( )
Хотя функция get_meta_tags( ) и не имеет прямого отношения к
преобразованию текста, зто весьма полезная функция, о которой следует
упомянуть. Синтаксис функции get_meta_tags( ):
array get_meta_tags (string имя_файла/URL [, int включение_пути])
Функция get_meta_tags( ) предназначена для поиска в файле HTML тегов
МЕТА.
Теги МЕТА содержат информацию о странице, используемую главным образом
поисковыми системами. Эти теги находятся внутри пары тегов
<head>...</head>. Применение тегов МЕТА продемонстрировано в
следующем фрагменте (назовем его example.html, поскольку он будет
использоваться в листинге 8.2):
<html>
<head>
<title>PHP Recipes</title>
<meta name="keywords" content="gourmet. PHP, food. code, recipes,
chef, programming, web">
<meta name="description" content="PHP Recipes provides savvy readers
with the latest in PHP
programming and gourmet cuisine!">
<meta name="author" content="WJ Gilmore">
</head>
Функция get_meta_tags( ) ищет в заголовке документа теги, начинающиеся
словом МЕТА, и сохраняет имена тегов и их содержимое в ассоциативном
массиве. В листинге 8.2 продемонстрировано применение этой функции к файлу
example.html.
Листинг 8.2. Извлечение тегов МЕТА из файла HTML функцией
get_meta_tags( )
$meta_tags = get_meta_tags("example.html"):
// Переменная $meta_tags содержит массив со следующей информацией:
// $meta_tags["keywords"] = "gourmet. PHP. food. code, recipes, chef,
programming. Web":
// $meta_tags["description"] = "PHP Recipes provides savvy readers with
the latest in PHP
programming and gourmet cuisine";
// $meta_tags["author"] = "WJ Gilmore";
Интересная подробность: данные тегов МЕТА можно извлекать не только из
файлов, находящихся на сервере, но и из других URL.
Теги МЕТА и их использование
превосходно описаны в статье Джо Берна (Joe Burn) на сайте HTML Goodies: http://htmlgoodies.earthweb.com/tutors/meta.html.
Преобразование строки к верхнему и нижнему регистру
В РНР существует четыре функции, предназначенных для изменения регистра
строки:
- strtolower( );
- strtoupper( );
- ucfirst( );
- ucwords( ).
Все эти функции подробно описаны ниже.
strtolower( )
Функция strtolower( ) преобразует все алфавитные символы строки к
нижнему регистру. Синтаксис функции strtolower( ):
string strtolower(string строка)
Неалфавитные символы функцией не изменяются. Преобразование строки к
нижнему регистру функцией strtolower( ) продемонстрировано в следующем
примере:
$sentence = "COOKING and PROGRAMMING PHP are my TWO favorite
pastimes!";
$sentence = strtolower($sentence);
// После вызова функции $sentence содержит строку
// "cooking and programming php are my two favorite pastimes!"
strtoupper( )
Строки можно преобразовывать не только к нижнему, но и к верхнему
регистру. Преобразование выполняется функцией strtoupper( ), имеющей
следующий синтаксис:
string strtoupper (string строка)
Неалфавитные символы функцией не изменяются. Преобразование строки к
верхнему регистру функцией strtoupper( ) продемонстрировано в следующем
примере:
$sentence = "cooking and programming PHP are my two favorite
pastimes!";
$sentence = strtoupper($sentence);
// После вызова функции $sentence содержит строку
// "COOKING AND PROGRAMMING PHP ARE MY TWO FAVORITE PASTIMES!"
ucfirst( )
Функция ucfirst( ) преобразует к верхнему регистру первый символ строки
- при условии, что он является алфавитным символом. Синтаксис функции
ucfirst( ):
string ucfirst (string строка)
Неалфавитные символы функцией не изменяются. Преобразование первого
символа строки функцией ucfirst( ) продемонстрировано в следующем
примере:
&sentence = "cooking and programming PHP are my two favorite
pastimes!";
$sentence = ucfirst($sentence);
// После вызова функции $sentence содержит строку
// "Cooking and programming PHP are mу two favorite pastimes!"
ucwords( )
Функция ucwords( ) преобразует к верхнему регистру первую букву каждого
слова в строке. Синтаксис функции ucwords( ):
string ucwords (string строка")
Неалфавитные символы функцией не изменяются. <Слово> определяется как
последовательность символов, отделенная от других элементов строки
пробелами. В следующем примере продемонстрировано преобразование первых
символов слов функцией ucwords( ):
$sentence = "cooking and programming PHP are my two favorite
pastimes!";
$sentence = ucwords($sentence);
// После вызова функции $sentence содержит строку
// "Cooking And Programming PHP Are My Two Favorite Pastimes!"
Проект: идентификация браузера
Каждый программист, пытающийся создать удобный web-сайт, должен
учитывать различия в форматировании страниц при просмотре сайта в разных
браузерах и операционных системах. Хотя консорциум W3 (http://www.w3.org)
продолжает публиковать стандарты, которых должны придерживаться
программисты при создании web-приложений, разработчики браузеров любят
дополнять эти стандарты своими маленькими <усовершенствованиями>, что в
конечном счете вызывает хаос и путаницу. Разработчики часто решают эту
проблему, создавая разные страницы для каждого типа браузера и
операционной системы - при этом объем работы значительно увеличивается, но
зато итоговый сайт идеально подходит для любого пользователя. Результат -
хорошая репутация сайта и уверенность в том, что пользователь посетит его
снова.
Чтобы пользователь мог просматривать страницу в формате,
соответствующем специфике его браузера и операционной системы, из
входящего запроса на получение страницы извлекается информация о браузере
и платформе. После получения необходимых данных пользователь
перенаправляется на нужную страницу.
Приведенный ниже проект (sniffer.php) показывает, как использовать
функции РНР для работы с регулярными выражениям с целью получения
информации по запросам. Программа определяет тип и версию браузера и
операционной системы, после чего выводит полученную информацию в окне
браузера. Но прежде чем переходить к непосредственному анализу программы,
я хочу представить один из главных ее компонентов - стандартную переменную
РНР $HTTP_USER_AGENT. В этой переменной в строковом формате хранятся
различные сведения о браузере и операционной системе пользователя - именно
то, что нас интересует. Эту информацию можно легко вывести на экран всего
одной командой:
<?
echo $HTTP USER_AGENT;
?>
При работе в Internet Explorer 5.0 на компьютере с Windows 98 результат
будет выглядеть так:
Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)
Для Netscape Navigator 4.75 выводятся следующие данные:
Mozilla/4.75 (Win98; U)
Sniffer.php извлекает необходимые данные из $HTTP_USER_AGENT при помощи
функций обработки строк и регулярных выражений. Алгоритм программы на
псевдокоде:
- Определить две функции для идентификации браузера и операционной
системы: browser_info( ) и opsys_info( ). Начнем с псевдокода функции
browser_info( ).
- Определить тип браузера, используя функцию егед( ). Хотя эта функция
работает медленнее упрощенных строковых функций типа strstr( ), в данном
случае она удобнее, поскольку регулярное выражение позволяет определить
версию браузера.
- Воспользоваться конструкцией if/elseif для идентификации следующих
браузеров и их версий: Internet Explorer, Opera, Netscape и браузер
неизвестного типа.
- Вернуть информацию о типе и версии браузера в виде массива.
- Функция opsys_info( ) определяет тип операционной системы. На этот
раз используется функция strstr( ), поскольку тип ОС определяется и без
применения регулярных выражений.
- Воспользоваться конструкцией if/elseif для идентификации следующих
систем: Windows, Linux, UNIX, Macintosh и неизвестная операционная
система.
- Вернуть информацию об операционной системе.
Листинг 8.3. Идентификация типа браузера и операционной системы
клиента
<?
/*
Файл : sniffer.php
Назначение: Идентификация типа/версии браузера и платформы
Автор: В. Дж. Гилмор
Дата : 24 августа 2000 г.
*/
// Функция: browser_info
// Назначение: Возвращает тип и версию браузера
function browser_info ($agent) {
// Определить тип браузера
// Искать сигнатуру Internet Explorer
if (ereg('MSIE ([0-9].[0-9]{1,2})', $agent, $version))
$browse_type = "IE";
$browse version = $version[1];
// Искать сигнатуру Opera
elseif (ereg( 'Opera ([0-9].[0-9]{1,2})'. $agent, $version)):
$browse_type = "Opera":
$browse_version = $version[1]:
// Искать сигнатуру Netscape. Проверка браузера Netscape
// *должна* выполняться после проверки Internet Explorer и Opera,
// поскольку все эти браузеры любят сообщать имя
// Mozilla вместе с настоящим именем.
elseif (ereg( 'Mozilla/([0-9].[0-9]{1,2})'. $agent, $version)) :
$browse_type = "Netscape";
$browse_version = $version[1];
// Если это не Internet Explorer, Opera или Netscape.
// значит, мы обнаружили неизвестный браузер,
else :
$browse_type = "Unknown";
$browse_version = "Unknown";
endif:
// Вернуть тип и версию браузера в виде массива
return array ($browse_type, $browse_version);
} // Конец функции browser_info
// Функция: opsys_info
// Назначение: Возвращает информацию об операционной системе
пользователя
function opsys_info($agent) {
// Идентифицировать операционную систему
// Искать сигнатуру Windows
if ( strstr ($agent. 'win') ) :
$opsys = "windows";
// Искать сигнатуру Linux
elseif ( strstr($agent, 'Linux') ) :
$opsys = "Linux";
// Искать сигнатуру UNIX
elseif ( strstr (Sagent, 'Unix') ) :
$opsys = "Unix";
// Искать сигнатуру Macintosh
elseif ( strstr ($agent, 'Mac') ) :
$opsys = "Macintosh";
// Неизвестная платформа else :
$opsys = "Unknown";
endif;
// Вернуть информацию об операционной системе
return $opsys;
} // Конец функции opsys_info
// Сохранить возвращаемый массив в списке
list ($browse_type. $browse_version) = browser_info ($HTTP_USER_AGENT);
Soperating_sys = opsysjnfo ($HTTP_USER_AGENT);
print "Browser Type: $browse_type <br>";
print "Browser Version: $browse_version <br>";
print "Operating System: $operating_sys <br>":
?>
Вот и все! Например, если пользователь работает в браузере Netscape
4.75 на компьютере с системой Windows, будет выведен следующий
результат:
Browser Type: Netscape
Browser Version: 4.75
Operating System: Windows
В следующей главе вы научитесь осуществлять переходы между страницами и
даже создавать списки стилей (style sheets) для конкретных операционной
системы и браузера.
Итоги
В этой главе был изложен довольно обширный материал. Какой прок от
языка программирования, если в нем нельзя работать с текстом? Мы
рассмотрели следующие темы:
- общие сведения о регулярных выражениях в стилях POSIX и Perl;
- стандартные функции РНР для работы с регулярными выражениями;
- изменение длины строки;
- определение длины строки;
- альтернативные функции РНР для обработки строковой информации;
- преобразование простого текста в HTML и наоборот;
- изменение регистра символов в строках.
Следующая глава открывает вторую часть книги - кстати, мою любимую. В
ней мы начнем знакомиться со средствами РНР, ориентированными на Web,
рассмотрим процесс динамического создания содержимого, включение файлов и
построение общих шаблонов. В дальнейших главах части 2 рассматриваются
работа с формами HTML, базы данных, отслеживание данных сеанса и
нетривиальные средства работы с шаблонами. Держитесь - начинается самое
интересное!