AdminWAPa.Ru
Учебник PHP, Глава 8
  • Глава 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.html://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&egrave;

      // Frac&ccediliaise' costs &lt; 42.25.";

      Функция htmlentities( ) в настоящее время работает только для символов кодировки ISO-8559-1 (ISO-Latin-1). Кроме того, она не преобразует пробелы в &nbsp;, как следовало бы ожидать.

      htmlspecialchars( )

      Функция htmlspecialchars( ) заменяет некоторые символы, имеющие особый смысл в контексте HTML, эквивалентными конструкциями HTML. Синтаксис функции htmlspecialchars( ):

      string htmlspecialchars (string строка)

      Функция html special chars( ) в настоящее время преобразует следующие символы:

      & преобразуется в &amp;; " " преобразуется в &quot;;

      < преобразуется в &lt;; > преобразуется в &gt;.

      В частности, эта функция позволяет предотвратить ввод пользователями разметки HTML в интерактивных web-приложениях (например, в электронных форумах). Ошибки, допущенные в разметке HTML, могут привести к тому, что вся страница будет формироваться неправильно. Впрочем, у этой задачи существует и более эффективное решение — полностью удалить теги из строки функцией strip_tags( ).

      Следующий пример демонстрирует удаление потенциально опасных символов функцией htmlspeclalchars( ):

      $user_input = "I just can't get «enough» of PHP & those fabulous cooking recipes!";

      $conv_input = htmlspecialchars($user_input);

      // $conv_input = "I just can't &lt;&lt;enough&gt;&gt; of PHP &amp 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 &eacute; il piatto pi&uacute; 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) «So, You Want a Meta Command, Huh?» на сайте 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, базы данных, отслеживание данных сеанса и нетривиальные средства работы с шаблонами. Держитесь — начинается самое интересное!

    • [ Назад | Содержание | Вперед ]