preg_split — Разбивает строку по регулярному выражению


Содержание

Методы RegExp и String

В этой главе мы рассмотрим все детали методов для работы с регулярными выражениями.

str.match(regexp)

Метод str.match(regexp) ищет совпадения с regexp в строке str .

У него есть три режима работы:

Если у регулярного выражения нет флага g , то он возвращает первое совпадение в виде массива со скобочными группами и свойствами index (позиция совпадения), input (строка поиска, равна str ):

Если у регулярного выражения есть флаг g , то он возвращает массив всех совпадений, без скобочных групп и других деталей.

Если совпадений нет, то, вне зависимости от наличия флага g , возвращается null .

Это очень важный нюанс. При отсутствии совпадений возвращается не пустой массив, а именно null . Если об этом забыть, можно легко допустить ошибку, например:

Если хочется, чтобы результатом всегда был массив, можно написать так:

str.matchAll(regexp)

Метод str.matchAll(regexp) – «новый, улучшенный» вариант метода str.match .

Он используется, в первую очередь, для поиска всех совпадений вместе со скобочными группами.

У него 3 отличия от match :

  1. Он возвращает не массив, а перебираемый объект с результатами, обычный массив можно сделать при помощи Array.from .
  2. Каждое совпадение возвращается в виде массива со скобочными группами (как str.match без флага g ).
  3. Если совпадений нет, то возвращается не null , а пустой перебираемый объект.

При переборе результатов matchAll в цикле for..of вызов Array.from , разумеется, не нужен.

str.split(regexp|substr, limit)

Разбивает строку в массив по разделителю – регулярному выражению regexp или подстроке substr.

Обычно мы используем метод split со строками, вот так:

Но мы можем разделить по регулярному выражению аналогичным образом:

str.searсh(regexp)

Метод str.search(regexp) возвращает позицию первого совпадения с regexp в строке str или -1 , если совпадения нет.

Важное ограничение: str.search умеет возвращать только позицию первого совпадения.

Если нужны позиции других совпадений, то следует использовать другой метод, например, найти их все при помощи str.matchAll(regexp) .

str.replace(str|regexp, str|func)

Это универсальный метод поиска-и-замены, один из самых полезных. Этакий швейцарский армейский нож для поиска и замены в строке.

Мы можем использовать его и без регулярных выражений, для поиска-и-замены подстроки:

Хотя есть подводный камень.

Когда первый аргумент replace является строкой, он заменяет только первое совпадение.

Вы можете видеть это в приведённом выше примере: только первый «-» заменяется на «:» .

Чтобы найти все дефисы, нам нужно использовать не строку «-» , а регулярное выражение /-/g с обязательным флагом g :

Второй аргумент – строка замены. Мы можем использовать специальные символы в нем:

Спецсимволы Действие в строке замены
$$ вставляет «$»
$& вставляет всё найденное совпадение
$` вставляет часть строки до совпадения
$’ вставляет часть строки после совпадения
$n если n это 1-2 значное число, то вставляет содержимое n-й скобки
$ вставляет содержимое скобки с указанным именем

Для ситуаций, которые требуют «умных» замен, вторым аргументом может быть функция.

Она будет вызываться для каждого совпадения, и её результат будет вставлен в качестве замены.

Функция вызывается с аргументами func(match, p1, p2, . pn, offset, input, groups) :

  1. match – найденное совпадение,
  2. p1, p2, . pn – содержимое скобок (см. главу Скобочные группы).
  3. offset – позиция, на которой найдено совпадение,
  4. input – исходная строка,
  5. groups – объект с содержимым именованных скобок (см. главу Скобочные группы).

Если скобок в регулярном выражении нет, то будет только 3 аргумента: func(match, offset, input) .

Например, переведём выбранные совпадения в верхний регистр:

Заменим каждое совпадение на его позицию в строке:

В примере ниже двое скобок, поэтому функция замены вызывается с 5-ю аргументами: первый – всё совпадение, затем два аргумента содержимое скобок, затем (в примере не используются) индекс совпадения и исходная строка:

Если в регулярном выражении много скобочных групп, то бывает удобно использовать остаточные аргументы для обращения к ним:

Или, если мы используем именованные группы, то объект groups с ними всегда идёт последним, так что можно получить его так:

Использование функции даёт нам максимальные возможности по замене, потому что функция получает всю информацию о совпадении, имеет доступ к внешним переменным и может делать всё, что угодно.

regexp.exec(str)

Метод regexp.exec(str) ищет совпадение с regexp в строке str . В отличие от предыдущих методов, вызывается на регулярном выражении, а не на строке.

Он ведёт себя по-разному в зависимости от того, имеет ли регулярное выражение флаг g .

Если нет g , то regexp.exec(str) возвращает первое совпадение в точности как str.match(regexp) . Такое поведение не даёт нам ничего нового.

Но если есть g , то:

  • Вызов regexp.exec(str) возвращает первое совпадение и запоминает позицию после него в свойстве regexp.lastIndex .
  • Следующий такой вызов начинает поиск с позиции regexp.lastIndex , возвращает следующее совпадение и запоминает позицию после него в regexp.lastIndex .
  • …И так далее.
  • Если совпадений больше нет, то regexp.exec возвращает null , а для regexp.lastIndex устанавливается значение 0 .

Таким образом, повторные вызовы возвращают одно за другим все совпадения, используя свойство regexp.lastIndex для отслеживания текущей позиции поиска.

В прошлом, до появления метода str.matchAll в JavaScript, вызов regexp.exec в цикле использовали для получения всех совпадений с их позициями и группами скобок в цикле:

Это работает и сейчас, хотя для современных браузеров str.matchAll , как правило, удобнее.

Мы можем использовать regexp.exec для поиска совпадения, начиная с нужной позиции, если вручную поставим lastIndex .

Если у регулярного выражения стоит флаг y , то поиск будет вестись не начиная с позиции regexp.lastIndex , а только на этой позиции (не далее в тексте).

В примере выше заменим флаг g на y . Ничего найдено не будет, поскольку именно на позиции 5 слова нет:

Это удобно в тех ситуациях, когда мы хотим «прочитать» что-то из строки по регулярному выражению именно на конкретной позиции, а не где-то далее.

Регулярные выражения

Регулярные выражения, это очень мощный, но в то же время сложный для понимания, инструмент обработки строк. Опишу основные моменты. Регулярное выражение это шаблон строки. По этому шаблону можно искать вхождения, производить замену, проверять на соответствие шаблону.

Правила составление шаблона (pattern)

Границы шаблона должны обозначаться определенными символами, часто используют «/«, но я предпочитаю использовать «#» потому, что от обилия прямых/обратных слешей может в глазах зарябить, а «решетки» обычно больше нигде не используются. Итак: «#ТутТелоРегулярногоВыражения#«

Внутри регулярного выражения используются скобки — это подвыражения, с которыми можно производить манипуляции, пример:

Это выражение предназначено для получения параметров в строке URL. В начале строки идет спецсимвол «^» — это означает начало строки. Далее идет «/catalog/» — тут нет спецсимволов, это просто текст, который должен содержатся в строке. Затем встретили круглые скобки, т.е. дошли до первого подвыражения. В квадратных скобках обозначаются множество символов, которые могут быть в строке в этом месте. Знак «» означает перечисление. Знак «\» экранирует специальные символы. Таким образом, в первом подвыражении у нас могут идти БОЛЬШИЕ и маленькие буквы латинского алфавита, цифры от 0 до 9, знак подчеркивания, тире и точка. Тире и точка — это спецсимволы, но здесь они экранированы, поэтому здесь это просто символы. После квадратных скобок идет знак «+» — это значит предыдущий символ (а у нас это множество символов заданное в квадратных скобках) может идти 1 или больше раз. Затем идет «/» — это просто символ, и аналогичное второе подвыражение. Затем идет «\.html«, что означает текст «.html«. А затем спец символы «.*» точка означает любой символ, а звездочка любое количество предыдущего символа. Т.е. после «.html» может идти все что угодно.

Указание количества, квантификаторы

Выше мы уже рассмотрели такие символы, указывающие количество предыдущих символов, как + и *. Приведем все возможности указания количества:

, где Х это число повторений, пример: [0-9] , это значит что здесь должно быть 5 цифр
, где X минимальное количество, Y — максимальное количество повторений. Пример [0-9] — 1 или 2 цифры. [0-9] -0, 1 или 2 цифры. [0-9] — 2 и более цифр
* любое количество символов (включая 0 символов)
+ 1 и более символов
? 1 или 0 символов

Спецсимволы

\ экранирование спецсимвола
\\ обратный слеш
| Метасимвол выбора (или или)
^ Метасимвол начала строки
$ Метасимвол конца строки
\n Символ перевода строки (шестнадцатеричный код 0x0A)
\r Символ возврата каретки (шестнадцатеричный код 0x0D)
\t Символ табуляции (шестнадцатеричный код 0x09)
. Точка. Любой символ.

Для некоторых групп символов есть специальные сокращения:

\d Цифра (0-9), вместо [0-9]
\D Не цифра (любой символ кроме символов 0-9)
\s Пустой символ (обычно пробел и символ табуляции)
\S Непустой символ (все, кроме символов, определяемых метасимволом \s)
\w «Словарный» символ (символ, который используется в словах. Обычно все буквы, все цифры и знак подчеркивания (‘_‘))
\W Все, кроме символов, определяемых метасимволом \w

«Жадность»

Рассмотрим понятие жадности регулярного выражения. Например есть строка:

«сейчас будет ссылка ссылка1, и еще ссылка2, итого 2 ссылки.«

Нужно получить ссылки, для этого составили выражение:

Вроди все верно, подвыражение подходит под:

Но оно также подходит под:

— его то мы и получим, т.к. регулярные выражения по умолчанию «жадные». Снять жадность можно с помощью модификатора «U«, вот так:

Модификаторы

После регулярного выражения могут идти модификаторы: «#ТутТелоРегулярногоВыражения#ТутМодификаторы» Виды модификаторов:

i Включает режим case-insensitive, т.е. большие и маленькие буквы в выражении не различаются.
m Указывает на то, что текст, по которому ведется поиск, должен рассматриваться как состоящий из нескольких строк. По умолчанию механизм регулярных выражений рассматривает текст как одну строку вне зависимости от того, чем она является на самом деле. Соответственно метасимволы ‘^’ и ‘$’ указывают на начало и конец всего текста. Если же этот модификатор указан, то они будут указывать соответственно на начало и конец каждой строки текста.
s По умолчанию метасимвол ‘.‘ не включает в свое определение символ перевода строки. Указание этого модификатора снимает это ограничение.
U Снимает жадность регулярного выражения
u Включает работу регулярных выражений с кириллицей в UTF-8, иначе работает не корректно.

php Функции для работы с регулярными выражениями

Ссылка на полный список функций. Тут приведу краткое описание некоторых функций. Внимание. описываемые ниже функции имеют больше возможностей, чем описываю я, все возможности можно посмотреть, перейдя по приведенной чуть выше ссылке.

preg_match

Выполняет проверку на соответствие регулярному выражению:

preg_match_all

Выполняет глобальный поиск шаблона в строке:

Возвращает количество найденных вхождений шаблона (которое может быть и нулем) либо FALSE, если во время выполнения возникли какие-либо ошибки. В переменную $res попадет результат поиска в виде массива: [0] содержит массив полных вхождений шаблона, элемент [1] содержит массив вхождений первой подмаски, и так далее. Для удобства работы с регулярными выражениями я создал страницу, где в режиме online можно поработать с функцией preg_match_all

preg_replace

Каждое значение может быть строкой или массивом, в случае, если $subject массив — возвращается массив, иначе строка

preg_split

Разбивает строку по регулярному выражению:

Возвращает массив, состоящий из подстрок заданной строки subject, которая разбита по границам, соответствующим шаблону pattern.

Разбить строку по символам php

Нам потребовалось разбить строк на символы. Давайте разберем несколько примеров и способов и несколько кодировок – они иногда играют неприятную роль в разбитии строки на элементы.

Самый простой и первый способ, который вы увидите, поиска в любом поисковике:

Разбить текст с помощью str_split

Нам понадобится текст, который будет в переменной.

Пропустим через функцию:

Если у вас windows-1251, то и для кириллицы этот способ вполне рабочий!

Разбить строку на символы, кириллица UTF-8

Довольно нагроможденный вариант разбития кириллического текста в на символы! А нет ли по проще варианта!?

Есть — именно он меняя и натолкнул на написание данной страницы! Потому. Что я раньше в таких случаях всегда пользовался этими непонятными и громоздкими вариантами!

$text=»Это просто текст»;

$str = iconv(«UTF-8», «windows-1251», $text);

foreach (str_split($str) as $index => $value)

$переменная .= iconv(«windows-1251″,»UTF-8″, $value).»
\n»;

Еще один вариант разбиения строки посимвольно, который я теперь использую:

preg_split — Разбивает строку по регулярному выражению

pattern — отсутствует, поэтому «//»

u — используется кодировка UTF-8

Специальное значение limit, равное -1, подразумевает отсутствие ограничения

PREG_SPLIT_NO_EMPTY — если этот флаг указан, функция preg_split() вернет только непустые подстроки.

Возвращает массив символов.

$text=»Это просто текст»;

print_r(preg_split(«//u», $text , -1, PREG_SPLIT_NO_EMPTY) ) ;

Регулярные выражения PHP

Что такое регулярные выражения?

PHP regexp — это мощный алгоритм сопоставления шаблонов, которое может быть выполнено в одном выражении. Регулярные выражения PHP используют арифметические операторы ( такие как +, -, ^ ) для создания сложных выражений.

Для чего используются регулярные выражения:

  • Регулярные выражения упрощают идентификацию строковых данных путем вызова одной функции. Это экономит время при составлении кода;
  • При проверке введенных пользователем данных, таких как адрес электронной почты, домен сайта, номер телефона, IP-адрес ;
  • Выделение ключевых слов в результатах поиска;
  • Регулярные выражения могут использоваться для идентификации тегов и их замены.

Регулярные выражения в PHP

PHP содержит встроенные функции, которые позволяют работать с регулярными выражениями. Теперь рассмотрим часто используемые функции регулярных выражений PHP .

  • preg_match — используется для выполнения сопоставления с шаблоном строки. Она возвращает true , если совпадение найдено, и false , если совпадение не найдено;
  • preg_split — используется для разбивки строки по шаблону, результат возвращается в виде числового массива;
  • preg_replace – используется для поиска по шаблону и замены на указанную строку.

Ниже приведен синтаксис функций регулярных выражений, таких как preg_match , preg_split или PHP regexp replace :

«имя_функции» — это либо preg_match , либо preg_split , либо preg_replace .
«/…/» — косые черты обозначают начало и конец регулярного выражения.
«‘/шаблон/’» — шаблон, который нам нужно сопоставить.
«объект» — строка, с которой нужно сопоставлять шаблон.

Теперь рассмотрим практические примеры использования упомянутых выше функций.

Preg_match

В первом примере функция preg_match используется для выполнения простого сопоставления шаблоном для слова guru в заданном URL-адресе .

В приведенном ниже коде показан вариант реализации данного примера:

Рассмотрим ту часть кода, которая отвечает за вывод «preg_match (‘/ guru /’, $ my_url)» .

«preg_match(…)» — функция PHP match regexp .
«‘/Guru/’» — шаблон регулярного выражения.
«$My_url» — переменная, содержащая текст, с которым нужно сопоставить шаблон.

Preg_split

Рассмотрим другой пример, в котором используется функция preg_split .

Мы возьмем фразу и разобьем ее на массив; шаблон предназначен для поиска единичного пробела:

Preg_replace

Рассмотрим функцию preg_replace , которая выполняет сопоставление с шаблоном и заменяет найденный результат другой строкой.

Приведенный ниже код ищет в строке слово guru . Он заменяет его кодом css , который задает цвет фона:

Метасимволы

В приведенных выше примерах использовались простые шаблоны. Метасимволы позволяют выполнять более сложные сопоставления шаблонов PHP regexp , такие как проверка адреса электронной почты. Рассмотрим часто используемые метасимволы.

Метасимвол Описание Пример
. Обозначает любой единичный символ, кроме символа новой строки. /./ — все, что содержит один символ.
^ Обозначает начало строки, не включая символ /. /^PH/ — любая строка, которая начинается с PH.
$ Обозначает шаблон в конце строки. /com$/ — guru99.com,yahoo.com и т.д.
* Обозначает любое количество символов, ноль или больше. /com*/ — computer, communication и т.д.
+ Требуется вхождение перед метасимволом символа (ов) хотя бы один раз. /yah+oo/ — yahoo.
Символ экранирования. /yahoo+.com/ — воспринимает точку, как дословное значение.
[…] Класс символов. /[abc]/ — abc.
a-z Обозначает строчные буквы. /a-z/ — cool, happy и т.д.
A-Z Обозначает заглавные буквы. /A-Z/ — WHAT, HOW, WHY и т.д.
0-9 Обозначает любые цифры от 0 до 9. /0-4/ — 0,1,2,3,4.

Теперь рассмотрим сложный PHP regexp пример, в котором проверяется валидность адреса электронной почты:

Результат: адрес электронной почты name@company.com является валидным.

Пояснение шаблона «[/^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+.[a-zA-Z.]<2,5>$/] «

«‘/…/’» начинает и завершает регулярное выражение.
«^[a-zA-Z0-9._-]» соответствует любым буквам в нижнем или верхнем регистре, цифрам от 0 до 9 и точкам, подчеркиваниям или тире.
«+@[a-zA-Z0-9-]» соответствует символу @ , за которым следуют буквы в нижнем или верхнем регистре, цифры от 0 до 9 или дефисы.
«+.[a-zA-Z.]<2,5>$/» указывает точку, используя обратную косую черту, затем должны следовать любые буквы в нижнем или верхнем регистре, количество символов в конце строки должно быть от 2 до 5.

Метасимволы являются полезными, когда речь идет о сопоставлении на соответствие шаблонам.

Заключение

  • PHP regexp — это алгоритм поиска по шаблону;
  • Регулярные выражения полезны при выполнении проверок валидности, создании HTML-шаблонов , которые распознают теги и т. д.;
  • PHP имеет встроенные функции для работы с регулярными выражениями: preg_match , preg_split и preg_replace ;
  • Метасимволы позволяют создавать сложные шаблоны.

Данная публикация представляет собой перевод статьи « PHP Regular Expressions » , подготовленной дружной командой проекта Интернет-технологии.ру

Очередной блог фрилансера

коротко и полезно о веб-разработке

15 регулярных выражений PHP в помощь веб-разработчику

Регулярные выражения – это очень полезный инструмент для разработчиков. С их помощью можно находить, определять или заменять текст, слова или любые другие символы. В сегодняшней статье собраны 15 наиболее полезных регулярных выражений, которые пригодятся любому веб-разработчику.

Введение в регулярные выражения

Многим начинающим разработчикам кажется, что регулярные выражения очень сложны для понимания и использования. На самом деле, все не так уж сложно, как может показаться. Прежде чем мы непосредственно перейдем к регулярным выражениям, с их полезным и универсальным кодом, давайте взглянем на основы:

Синтаксис регулярных выражений

Регулярное выражение Означает
foo Строка “foo”
^foo Строка начинается с “foo”
foo$ Строка заканчивается на “foo”
^foo$ «foo» встречается в строке только один раз
[abc] a, b, или c
[a-z] любой символ в нижнем регистре
[^A-Z] любой символ, не находящийся в верхнем регистре
(gif|jpg) Означает как «gif” так и “jpeg”
[a-z]+ Один или более символов нижнего регистра
[0-9.-] Любая цифра, точка или знак минус
^[a-zA-Z0-9_]<1,>$ Любое слово, хотя бы одна буква, число или _
([wx])([yz]) wy, wz, xy, или xz
(^A-Za-z0-9) Любой символ (не число и не буква)
([A-Z]<3>|[0-9]<4>) Означает три буквы или 4 цифры

PHP-функции для регулярных выражений

Функция Описание
preg_match() Функция preg_match() ищет строку по заданному шаблону, возвращает true, если строка находится и false, в остальных случаях
preg_match_all() Функция preg_match_all() находит все вхождения строки, заданной по шаблону
preg_replace() Функция preg_replace(), действует по тому же принципу, что и ereg_replace(), за исключением того, что регулярные выражения можно использовать как для задания шаблона поиска, так и для строки, на которую следует заменить, найденное значение.
preg_split() Функция preg_split(), действует так же как split(), за исключением того, что регулярное выражение можно использовать в качестве параметра для шаблона поиска.
preg_grep() Функция preg_grep() ищет все элементы входного массива, возвращая все элементы, соответствующие шаблону регулярного выражения.
preg_quote() Экранирует символы регулярного выражения

Проверка доменного имени

Проверяем, является ли строка правильным доменным именем

Подсветка слова в тексте

Это очень полезное регулярное выражение, с его помощью вы можете найти нужное слово и подсветить его. Особенно полезно для отображения результатов поиска.

Подсветка результатов поиска в WordPress блоге

Как уже говорилось в предыдущем примере, этот пример кода, удобно использовать в выдаче поисковых результатов и есть отличный способ внедрить эту функцию в wordpress-блог.

Откройте ваш файл search.php, и найдите функцию the_title(). Замените ее следующим кодом:

Теперь, выше этой строки, добавьте этот код:

Сохраните файл search.php, и откройте style.css. Добавьте следующую строку:

Получение всех картинок из HTML-документа

Если вам когда-нибудь требовалось получить все картинки с веб-страницы, этот код должен быть Вы легко сможете создать загрузчик изображений с помощью возможностей cURL

Удаление повторяющихся слов (не чувствителен к регистру)

Во время печатания, часто повторяются слова? Поможет это регулярное выражение.

Удаление повторяющейся пунктуации

То же самое, только для пунктуации. Попрощайтесь с двойными запятыми.

Поиск XML/HTML тэгов

Эта простая функция, принимает два аргумента. Первый – это тэг, который вам нужно найти, и второй – это переменная, содержащая XML или HTML. Повторюсь, эту функцию очень удобно использовать вместе с cURL.

Поиск XHTML/XML тэгов с определенным значением атрибута

Эта функция очень похожа на предыдущую, за исключением того, что вы можете задать тегу нужный атрибут. Например, вы легко сможете найти

Поиск шестнадцатеричных значений цветов

Еще один полезный инструмент для веб-разработчика! Он позволяет вам находить/проверять шестнадцатеричные значение цвета.

Поиск заголовка статьи

Этот фрагмент кода найдет и выведет на экран текст, находящийся внутри тэгов , на html-странице.

Парсинг логов Apache

Большинство сайтов запущено на всем известном веб-сервере Apache. Если ваш сайт находится в их числе, почему бы не использовать PHP и регулярные выражения для разбора логов апача?

Замена двойных кавычек “умными” кавычками

Если вы любитель типографики, вам понравится это регулярное выражение, заменяющее обычные двойные кавычки, на “умные кавычки”. Похожее регулярное выражение используется в wordpress в контенте страницы.

Комплексная проверка пароля

Это регулярное выражение будет следить за тем, чтобы в текстовое поле было введено не менее шести символов, цифры, дефисы и подчеркивания.

Текстовое поле должно содержать как минимум один символ верхнего регистра, один нижнего регистра и одну цифру.

WordPress: Использование регулярного выражения для получения картинок из записи

Поскольку многие из вас являются пользователями WordPress, вам возможно пригодится код, который позволяет получить все картинки, из текста статьи, и вывести их.

Для того, чтобы использовать этот код, просто вставьте его в любой файл вашей темы.

Генерация автоматических смайлов

Другая функция, используемая в wordpress – позволяет автоматически заменять символы смайлов на картинку смайла.

Перевод статьи “15 PHP regular expressions for web developers”, автор Jean-Baptiste Jung

Рассказать друзьям

Понравилась статья? Лучший способ сказать спасибо — поделиться ссылкой в социальных сетях:

Разбить строку на предложения с помощью регулярных выражений

У меня случайный текст хранится в $sentences , Используя регулярные выражения, я хочу разбить текст на предложения, см .:

Тем не менее, он не разделяется на предложения, если есть символы Unicode:

Или этот сценарий:

Что я могу сделать, чтобы это работало, когда в тексте есть символы Юникода?

Вот > для тестирования.

Информация о наградах

Я ищу полное решение для этого. Прежде чем публиковать ответ, пожалуйста, прочтите ветку комментариев, которую я имел с WiktorStribiżew для получения более актуальной информации по этому вопросу.

Решение

Как и следовало ожидать, любая обработка естественного языка не является тривиальной задачей. Причина в том, что они являются эволюционными системами. Нет ни одного человека, который бы сидел и думал о том, какие хорошие идеи, а какие — нет. Каждое правило имеет 20-40% исключений. С учетом вышесказанного, сложность одного регулярного выражения, которое может делать ваши ставки, будет вне графика. Тем не менее, следующее решение опирается в основном на регулярные выражения.

  • Идея состоит в том, чтобы постепенно пройти через текст.
  • В любой момент времени текущая часть текст будет содержаться в двух разных частях. Один, который является кандидатом на подстроку до граница предложения и другое — после.
  • Первые 10 пар регулярных выражений определяют позиции, которые выглядят как границы предложений, но на самом деле это не так. В таком случае, до а также после продвигаются без регистрации нового предложения.
  • Если ни одна из этих пар не совпадает, будет предпринята попытка сопоставления с последними 3 парами, возможно обнаружив границу.

Что касается откуда взялись эти регулярные выражения? — я перевел эта библиотека Ruby , который генерируется на основе Эта бумага . Если вы действительно хотите понять их, нет другого выбора, кроме как читать газету.

Что касается точности — я призываю вас проверить это с различными текстами. После некоторых экспериментов я был очень приятно удивлен.

С точки зрения производительности — регулярные выражения должны быть очень производительными, так как все они имеют \A или же \Z якорь, квантификаторы повторения почти отсутствуют, а в местах, где они есть, обратного отслеживания быть не может. Тем не менее, регулярные выражения являются регулярными выражениями. Вам нужно будет сделать несколько тестов, если вы планируете использовать эти узкие циклы на огромных кусках текста.

Обязательный отказ от ответственности: извините мои ржавые навыки PHP. Следующий код, возможно, не самый идиоматический php, он должен быть достаточно ясным, чтобы понять суть.

Другие решения

 это то, на что это похоже, когда вы печатаете UTF-8 символ U + 00A0 Non-Breaking Space на страницу / консоль, интерпретируемую как Latin-1. Поэтому я думаю, что у вас есть неразрывный пробел между предложениями, а не нормальный пробел.

\s может соответствовать неразрывному пробелу, но вам нужно будет использовать /u модификатор, сообщающий preg, что вы отправляете ему строку в кодировке UTF-8. В противном случае он, как и ваша команда печати, будет угадывать Latin-1 и видеть его как два символа. Â ,

Если пробелы ненадежны, то вы можете использовать совпадение на . с последующим любым количеством пробелов, с большой буквы.

Вы можете сопоставить любую заглавную букву UTF-8, используя Свойство Unicode \p ,

Вам нужно только исключить сокращения, которые, как правило, следуют за собственными именами (имена людей, названия компаний и т. Д.), Поскольку они начинаются с заглавной буквы.

Примечание. Этот ответ может быть недостаточно точным для вашей ситуации. Я не могу судить об этом. Это решает проблему, как описано выше, и легко понятно.

Я считаю, что невозможно получить пуленепробиваемый сплиттер предложений, учитывая, что пользовательский контент не всегда грамматически и синтаксически корректен. Более того, достичь 100% правильных результатов просто невозможно из-за технического несовершенства инструментов для чистки / получения контента, которые могут не получить чистое содержимое, которое будет содержать пробелы или пунктуацию. И, наконец, бизнес теперь более склонен к достаточно хорошо стратегии, и если вам удастся разбить текст на 95% раз, это в большинстве случаев считается успехом.

Теперь любая задача разделения предложений — это задача НЛП, и одного, двух или трех регулярных выражений недостаточно. Вместо того, чтобы думать о собственной цепочке регулярных выражений, я бы посоветовал использовать для этого некоторые существующие библиотеки NLP.

  1. php-предложение Вандерли (зависит от разумно грамматически правильной пунктуации)

Ниже приведен приблизительный список правил, используемых для разделения предложений.

  • Каждый перевод строки разделяет предложения.
  • В конце текста указывается конец, если предложение, если не указано иное, завершается правильной пунктуацией.
  • Предложения должны состоять как минимум из двух слов, за исключением перевода строки или конца текста.
  • Пустая строка не является предложением.
  • Каждый вопрос или восклицательный знак или их комбинация считается концом предложения.
  • Отдельный период считается концом предложения, если только …
    • Ему предшествует одно слово, или …
    • За ним следует одно слово.
  • Последовательность нескольких периодов не считается концом предложения.
  1. NlpTools это еще одна библиотека, которую вы можете использовать для этой задачи. Вот пример кода, реализующего простой на основе правил токенизатор предложений:
  1. Вы можете получить PHP / JAVA мост для использования Java StanfordNLP (здесь Пример Java разбиения текста на предложения).

ВАЖНАЯ ЗАМЕТКА: Большинство протестированных мною моделей НЛП плохо обрабатывают склеенные предложения. Однако, если вы добавите пробел после знака препинания, качество разбиения предложений повысится. Просто добавьте это перед отправкой текста в функцию разделения предложения:

Хенрик Петтерсон Пожалуйста, прочитайте его полностью, потому что мне нужно повторить несколько вещей, которые уже были сказаны выше.

Как уже упоминалось выше, многие люди упоминали, что если вы добавите модификатор \ u, он будет работать с символом Unicode: ПРАВДА и это Работает отлично в приведенном ниже примере

Ваши примеры, которые вы привели в комментариях, были не работает, потому что Oни не должно быть пробелов между двумя предложениями. И твой код с указанием именно того, что там должен быть пробелом между предложениями.

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

Существует довольно сложный алгоритм Unicode Text Segmentation, который работает с различными текстовыми границами, включая границы предложений.

Самая известная реализация этих алгоритмов — ICU.

Я нашел этот класс: http://php.net/manual/en/ > однако, похоже, что это в git, а не в мейнстриме.

Так что если вы хотите решить эту ОЧЕНЬ сложную проблему в лучшем случае, почему я бы предложил:

  • Получить этот класс откуда-то
  • Напишите небольшой плагин PHP, который оборачивает нужные вам функции ICU — это на самом деле довольно просто, если вы создаете определенные функции.

Разбить строку в конце пробела перед разделителем Используя preg_split?

Я пытаюсь использовать preg_split, чтобы разделить следующую строку в каждом пробеле перед косой чертой. Я знаю, что это будет простой REGEX, но я не могу понять это, используя RegExr?

Мне нужно разбить строку в последнем пробеле перед каждым /, чтобы получить следующий результат: [ 113]

Любая помощь будет оценена!

2 ответа

В случае если не нужно быть регулярным выражением…

Вы можете использовать предварительное утверждение:

Регулярное выражение

  • @ разделитель regex ; обычно в качестве разделителя используется / , но это регулярное выражение пытается сопоставить / , и поэтому лучше использовать другой разделитель;
  • за ним следует пробел; это пространство, которое вы хотите использовать в качестве разделителя для разделения входной строки;
  • ( запускает группу; группа нужна утверждению;
  • ?= — положительное утверждение, ориентированное на будущее; требует, чтобы группа соответствовала входной строке, но не потребляет символы из входной строки, которая соответствует группе;
  • [^ ]*/ — содержимое группы; он соответствует любому непробельному символу любое количество раз, за ​​которым следует / ; это слово содержит косую черту ( / );
  • ) оканчивает группу.

В целом, regex соответствует пробелам, за которыми следует слово, которое содержит косую черту, но слово не используется; он не включен в разделитель в preg_split() , используется только пробел.

Regex. Split Метод

Определение

Разделяет входную строку в массив подстрок в позициях, определенных соответствием регулярного выражения. Splits an input string into an array of substrings at the positions defined by a regular expression match.

Перегрузки

Разделяет входную строку в массив подстрок в позициях, определенных указанным шаблоном регулярного выражения. Splits an input string into an array of substrings at the positions defined by a specified regular expression pattern. Дополнительные параметры определяют параметры, которые изменяют соответствующую операцию и интервал времени ожидания, если совпадение не найдено. Additional parameters specify options that modify the matching operation and a time-out interval if no match is found.

Разделяет входную строку в массив подстрок в позициях, определенных указанным шаблоном регулярного выражения. Splits an input string into an array of substrings at the positions defined by a specified regular expression pattern. Указанные параметры изменяют операцию сопоставления. Specified options modify the matching operation.

Разделяет входную строку указанное максимальное количество раз в массив подстрок в позициях, определенных регулярным выражением, указанным в конструкторе Regex. Splits an input string a specified maximum number of times into an array of substrings, at the positions defined by a regular expression specified in the Regex constructor. Поиск шаблона регулярного выражения начинается с указанной позиции элемента во входной строке. The search for the regular expression pattern starts at a specified character position in the input string.

Разделяет входную строку указанное максимальное количество раз в массив подстрок в позициях, определенных регулярным выражением, указанным в конструкторе Regex. Splits an input string a specified maximum number of times into an array of substrings, at the positions defined by a regular expression specified in the Regex constructor.

Разделяет входную строку в массив подстрок в позициях, определенных шаблоном регулярного выражения, указанным в конструкторе Regex. Splits an input string into an array of substrings at the positions defined by a regular expression pattern specified in the Regex constructor.

Разделяет входную строку в массив подстрок в позициях, определенных шаблоном регулярного выражения. Splits an input string into an array of substrings at the positions defined by a regular expression pattern.

Split(String, String, RegexOptions, TimeSpan)

Разделяет входную строку в массив подстрок в позициях, определенных указанным шаблоном регулярного выражения. Splits an input string into an array of substrings at the positions defined by a specified regular expression pattern. Дополнительные параметры определяют параметры, которые изменяют соответствующую операцию и интервал времени ожидания, если совпадение не найдено. Additional parameters specify options that modify the matching operation and a time-out interval if no match is found.

Параметры

Строка для разделения. The string to split.

Шаблон регулярного выражения для сопоставления. The regular expression pattern to match.

Побитовая комбинация значений перечисления, предоставляющая параметры для сопоставления. A bitwise combination of the enumeration values that provide options for matching.

Интервал времени ожидания или InfiniteMatchTimeout, чтобы указать, что метод не должен превышать время ожидания. A time-out interval, or InfiniteMatchTimeout to indicate that the method should not time out.

Возвраты

Массив строк. A string array.

Исключения

Произошла ошибка анализа регулярного выражения. A regular expression parsing error occurred.

Значение параметра input или pattern — null . input or pattern is null .

options не является допустимой битовой комбинацией значений RegexOptions . options is not a valid bitwise combination of RegexOptions values.

— или — -or- Значение параметра matchTimeout отрицательное, равно нулю или больше, чем приблизительно 24 дня. matchTimeout is negative, zero, or greater than approximately 24 days.

Время ожидания истекло. A time-out occurred. Дополнительные сведения о времени ожидания см. в разделе «Примечания». For more information about time-outs, see the Remarks section.

Комментарии

Методы похожи на метод, за исключением того, Regex.Split что разделяет строку с разделителем, определенным регулярным выражением, а не набором символов. String.Split(Char[]) Regex.Split The Regex.Split methods are similar to the String.Split(Char[]) method, except that Regex.Split splits the string at a delimiter determined by a regular expression instead of a set of characters. Строка разделяется столько раз, сколько возможно. The string is split as many times as possible. Если разделитель не найден, возвращаемое значение содержит один элемент, значение которого является исходной input строкой. If no delimiter is found, the return value contains one element whose value is the original input string.

pattern Параметр состоит из элементов языка регулярных выражений, которые в символьном виде описывают строку для сопоставления. The pattern parameter consists of regular expression language elements that symbolically describe the string to match. Дополнительные сведения о регулярных выражениях см. в разделе .NET Framework регулярные выражения и Язык регулярных выражений — краткий справочник. For more information about regular expressions, see .NET Framework Regular Expressions and Regular Expression Language — Quick Reference.

Скомпилированные регулярные выражения, используемые в вызовах статических Split методов, кэшируются автоматически. Compiled regular expressions used in calls to static Split methods are automatically cached. Для самостоятельного управления временем существования скомпилированных регулярных выражений используйте Split методы экземпляра. To manage the lifetime of compiled regular expressions yourself, use the instance Split methods.

Если несколько совпадений находятся рядом друг с другом, в массив вставляется пустая строка. If multiple matches are adjacent to one another, an empty string is inserted into the array. Например, разбиение строки на один дефис приводит к тому, что возвращаемый массив включает пустую строку в позицию, где обнаружены два смежных дефиса. For example, splitting a string on a single hyphen causes the returned array to include an empty string in the position where two adjacent hyphens are found.

Если совпадение находится в начале или в конце входной строки, то в начале или конце возвращаемого массива включается пустая строка. If a match is found at the beginning or the end of the input string, an empty string is included at the beginning or the end of the returned array. В следующем примере шаблон [a-z]+ регулярного выражения используется для разбиения входной строки на любой алфавитный символ в верхнем или нижнем регистре. The following example uses the regular expression pattern [a-z]+ to split an input string on any uppercase or lowercase alphabetic character. Поскольку строка начинается и заканчивается соответствующими буквами, значением первого и последнего элемента возвращаемого массива является String.Empty. Because the string begins and ends with matching alphabetic characters, the value of the first and last element of the returned array is String.Empty.

Если в Regex.Split выражении используются скобки записи, любой захваченный текст включается в результирующий массив строк. If capturing parentheses are used in a Regex.Split expression, any captured text is included in the resulting string array. Например, если разделить строку «Плам-груш» на дефис, помещенный в круглые скобки, возвращаемый массив включает строковый элемент, содержащий дефис. For example, if you split the string «plum-pear» on a hyphen placed within capturing parentheses, the returned array includes a string element that contains the hyphen.

Однако если шаблон регулярного выражения включает несколько наборов скобок записи, поведение этого метода зависит от версии .NET Framework. However, when the regular expression pattern includes multiple sets of capturing parentheses, the behavior of this method depends on the version of the .NET Framework. В .NET Framework 1,0 и 1,1, если совпадение не найдено в первом наборе скобок записи, записанный текст из дополнительных скобок записи не включается в возвращаемый массив. In the .NET Framework 1.0 and 1.1, if a match is not found within the first set of capturing parentheses, captured text from additional capturing parentheses is not included in the returned array. Начиная с .NET Framework 2,0, весь захваченный текст также добавляется в возвращаемый массив. Starting with the .NET Framework 2.0, all captured text is also added to the returned array. Например, следующий код использует два набора скобок записи для извлечения элементов даты, включая разделители даты, из строки даты. For example, the following code uses two sets of capturing parentheses to extract the elements of a date, including the date delimiters, from a date string. Первый набор скобок записи захватывает дефис, а второй набор захватывает косую черту. The first set of capturing parentheses captures the hyphen, and the second set captures the forward slash. Если пример кода компилируется и выполняется с .NET Framework 1,0 или 1,1, он исключает символы косой черты. Если он компилируется и запускается в .NET Framework 2,0 или более поздних версиях, он включает их. If the example code is compiled and run under the .NET Framework 1.0 or 1.1, it excludes the slash characters; if it is compiled and run under the .NET Framework 2.0 or later versions, it includes them.

Если регулярное выражение может соответствовать пустой строке, будет Split разделять строку на массив односимвольных строк, так как разделитель пустых строк можно найти в каждом расположении. If the regular expression can match the empty string, Split will split the string into an array of single-character strings because the empty string delimiter can be found at every location.

matchTimeout Параметр указывает, как долго метод сопоставления шаблонов должен пытаться найти соответствие до истечения времени ожидания. Установка интервала времени ожидания предотвращает зависание регулярных выражений, которые полагаются на избыточное выполнение поиска с возвратом, при обработке входных данных, содержащих близкие совпадения. The matchTimeout parameter specifies how long a pattern matching method should try to find a match before it times out. Setting a time-out interval prevents regular expressions that rely on excessive backtracking from appearing to stop responding when they process input that contains near matches. Дополнительные сведения см. в разделе рекомендации по использованию регулярных выражений и поискас возвратом. For more information, see Best Practices for Regular Expressions and Backtracking. Если в течение этого интервала времени совпадения не найдены, метод создает RegexMatchTimeoutException исключение. If no match is found in that time interval, the method throws a RegexMatchTimeoutException exception. matchTimeout переопределяет любое значение времени ожидания по умолчанию, определенное для домена приложения, в котором выполняется метод. matchTimeout overrides any default time-out value defined for the application domain in which the method executes.

Примечания для тех, кто вызывает этот метод

Рекомендуется присвоить matchTimeout параметру соответствующее значение, например две секунды. We recommend that you set the matchTimeout parameter to an appropriate value, such as two seconds. Если вы отключаете время ожидания, указав InfiniteMatchTimeout, механизм регулярных выражений обеспечивает немного более высокую производительность. If you disable time-outs by specifying InfiniteMatchTimeout, the regular expression engine offers slightly better performance. Однако время ожидания следует отключить только при следующих условиях. However, you should disable time-outs only under the following conditions: — Если входные данные, обрабатываемые регулярным выражением, являются производными от известного и надежного источника или состоят из статического текста. — When the input processed by a regular expression is derived from a known and trusted source or consists of static text. Это исключает текст, введенный пользователями динамически. This excludes text that has been dynamically input by users.

— При тщательном тестировании шаблона регулярного выражения для обеспечения эффективной обработки совпадений, несоответствий и близких соответствий. — When the regular expression pattern has been thoroughly tested to ensure that it efficiently handles matches, non-matches, and near matches.

— Если шаблон регулярного выражения не содержит элементов языка, которые вызывают избыточный поиск с возвратом при обработке близкого соответствия. — When the regular expression pattern contains no language elements that are known to cause excessive backtracking when processing a near match.

Дополнительно

Split(String, String, RegexOptions)

Разделяет входную строку в массив подстрок в позициях, определенных указанным шаблоном регулярного выражения. Splits an input string into an array of substrings at the positions defined by a specified regular expression pattern. Указанные параметры изменяют операцию сопоставления. Specified options modify the matching operation.

Параметры

Строка для разделения. The string to split.

Шаблон регулярного выражения для сопоставления. The regular expression pattern to match.

Побитовая комбинация значений перечисления, предоставляющая параметры для сопоставления. A bitwise combination of the enumeration values that provide options for matching.

Возвраты

Массив строк. An array of strings.

Исключения

Произошла ошибка анализа регулярного выражения. A regular expression parsing error occurred.

Значение параметра input или pattern — null . input or pattern is null .

Параметр options не является допустимой битовой комбинацией значений RegexOptions. options is not a valid bitwise combination of RegexOptions values.

Время ожидания истекло. A time-out occurred. Дополнительные сведения о времени ожидания см. в разделе «Примечания». For more information about time-outs, see the Remarks section.

Комментарии

Методы похожи на метод, за исключением того, Regex.Split что разделяет строку с разделителем, определенным регулярным выражением, а не набором символов. String.Split(Char[]) Regex.Split The Regex.Split methods are similar to the String.Split(Char[]) method, except that Regex.Split splits the string at a delimiter determined by a regular expression instead of a set of characters. Строка разделяется столько раз, сколько возможно. The string is split as many times as possible. Если разделитель не найден, возвращаемое значение содержит один элемент, значение которого является исходной input строкой. If no delimiter is found, the return value contains one element whose value is the original input string.

pattern Параметр состоит из элементов языка регулярных выражений, которые в символьном виде описывают строку для сопоставления. The pattern parameter consists of regular expression language elements that symbolically describe the string to match. Дополнительные сведения о регулярных выражениях см. в разделе .NET Framework регулярные выражения и Язык регулярных выражений — краткий справочник. For more information about regular expressions, see .NET Framework Regular Expressions and Regular Expression Language — Quick Reference.

Скомпилированные регулярные выражения, используемые в вызовах статических Split методов, кэшируются автоматически. Compiled regular expressions used in calls to static Split methods are automatically cached. Для самостоятельного управления временем существования скомпилированных регулярных выражений используйте Split методы экземпляра. To manage the lifetime of compiled regular expressions yourself, use the instance Split methods.

Если несколько совпадений находятся рядом друг с другом, в массив вставляется пустая строка. If multiple matches are adjacent to one another, an empty string is inserted into the array. Например, разбиение строки на один дефис приводит к тому, что возвращаемый массив включает пустую строку в позицию, где обнаружены два смежных дефиса. For example, splitting a string on a single hyphen causes the returned array to include an empty string in the position where two adjacent hyphens are found.

Если совпадение находится в начале или в конце входной строки, то в начале или конце возвращаемого массива включается пустая строка. If a match is found at the beginning or the end of the input string, an empty string is included at the beginning or the end of the returned array. В следующем примере шаблон [a-z]+ регулярного выражения используется для разбиения входной строки на любой алфавитный символ в верхнем или нижнем регистре. The following example uses the regular expression pattern [a-z]+ to split an input string on any uppercase or lowercase alphabetic character. Поскольку строка начинается и заканчивается соответствующими буквами, значением первого и последнего элемента возвращаемого массива является String.Empty. Because the string begins and ends with matching alphabetic characters, the value of the first and last element of the returned array is String.Empty.

Если в Regex.Split выражении используются скобки записи, любой захваченный текст включается в результирующий массив строк. If capturing parentheses are used in a Regex.Split expression, any captured text is included in the resulting string array. Например, если разделить строку «Плам-груш» на дефис, помещенный в круглые скобки, возвращаемый массив включает строковый элемент, содержащий дефис. For example, if you split the string «plum-pear» on a hyphen placed within capturing parentheses, the returned array includes a string element that contains the hyphen.

Однако если шаблон регулярного выражения включает несколько наборов скобок записи, поведение этого метода зависит от версии .NET Framework. However, when the regular expression pattern includes multiple sets of capturing parentheses, the behavior of this method depends on the version of the .NET Framework. В .NET Framework 1,0 и 1,1, если совпадение не найдено в первом наборе скобок записи, записанный текст из дополнительных скобок записи не включается в возвращаемый массив. In the .NET Framework 1.0 and 1.1, if a match is not found within the first set of capturing parentheses, captured text from additional capturing parentheses is not included in the returned array. Начиная с .NET Framework 2,0, весь захваченный текст также добавляется в возвращаемый массив. Starting with the .NET Framework 2.0, all captured text is also added to the returned array. Например, следующий код использует два набора скобок записи для извлечения элементов даты, включая разделители даты, из строки даты. For example, the following code uses two sets of capturing parentheses to extract the elements of a date, including the date delimiters, from a date string. Первый набор скобок записи захватывает дефис, а второй набор захватывает косую черту. The first set of capturing parentheses captures the hyphen, and the second set captures the forward slash. Если пример кода компилируется и выполняется с .NET Framework 1,0 или 1,1, он исключает символы косой черты. Если он компилируется и запускается в .NET Framework 2,0 или более поздних версиях, он включает их. If the example code is compiled and run under the .NET Framework 1.0 or 1.1, it excludes the slash characters; if it is compiled and run under the .NET Framework 2.0 or later versions, it includes them.

Если регулярное выражение может соответствовать пустой строке, будет Split разделять строку на массив односимвольных строк, так как разделитель пустых строк можно найти в каждом расположении. If the regular expression can match the empty string, Split will split the string into an array of single-character strings because the empty string delimiter can be found at every location.

RegexMatchTimeoutException Исключение возникает, если время выполнения операции разбиения превышает интервал времени ожидания, указанный для домена приложения, в котором вызывается метод. The RegexMatchTimeoutException exception is thrown if the execution time of the split operation exceeds the time-out interval specified for the application domain in which the method is called. Если время ожидания не определено в свойствах домена приложения или если значение времени ожидания равно Regex.InfiniteMatchTimeout, исключение не создается. If no time-out is defined in the application domain’s properties, or if the time-out value is Regex.InfiniteMatchTimeout, no exception is thrown.

Примечания для тех, кто вызывает этот метод

Время ожидания этого метода истекает через интервал, равный значению времени ожидания по умолчанию для домена приложения, в котором вызывается метод. This method times out after an interval that is equal to the default time-out value of the application domain in which the method is called. Если для домена приложения не определено значение времени ожидания, то используется значение InfiniteMatchTimeout, запрещающее истечение времени ожидания метода. If a time-out value has not been defined for the application domain, the value InfiniteMatchTimeout, which prevents the method from timing out, is used. Для разделения текста в шаблоне Split(String, String, RegexOptions, TimeSpan)рекомендуется использовать статический метод, который позволяет задать интервал времени ожидания. The recommended static method for splitting text on a pattern match is Split(String, String, RegexOptions, TimeSpan), which lets you set the time-out interval.

Дополнительно

Split(String, Int32, Int32)

Разделяет входную строку указанное максимальное количество раз в массив подстрок в позициях, определенных регулярным выражением, указанным в конструкторе Regex. Splits an input string a specified maximum number of times into an array of substrings, at the positions defined by a regular expression specified in the Regex constructor. Поиск шаблона регулярного выражения начинается с указанной позиции элемента во входной строке. The search for the regular expression pattern starts at a specified character position in the input string.

Параметры

Строка для разделения. The string to be split.

Максимальное количество возможных случаев разделения. The maximum number of times the split can occur.

Позиция символа во входной строке, с которой начинается поиск. The character position in the input string where the search will begin.

Возвраты

Массив строк. An array of strings.

Исключения

Свойство input имеет значение null . input is null .

Параметр startat имеет значение меньше нуля или больше длины input . startat is less than zero or greater than the length of input .

Время ожидания истекло. A time-out occurred. Дополнительные сведения о времени ожидания см. в разделе «Примечания». For more information about time-outs, see the Remarks section.

Комментарии

Методы похожи на метод, за исключением того, Regex.Split что разделяет строку с разделителем, определенным регулярным выражением, а не набором символов. String.Split Regex.Split The Regex.Split methods are similar to the String.Split method, except that Regex.Split splits the string at a delimiter determined by a regular expression instead of a set of characters. Параметр задает максимальное число подстрок, на input которые разделяется строка. Последняя строка содержит неразделенную оставшуюся часть строки. count The count parameter specifies the maximum number of substrings into which the input string is split; the last string contains the unsplit remainder of the string. Нулевое count значение обеспечивает по умолчанию разделение как можно меньшего числа раз. A count value of zero provides the default behavior of splitting as many times as possible. startat Параметр определяет точку, в которой начинается поиск первого разделителя (он может использоваться для пропуска начальных пробелов). The startat parameter defines the point at which the search for the first delimiter begins (this can be used for skipping leading white space).

Если в строке count + 1 не найдено совпадений, метод возвращает одноэлементный массив, input содержащий строку. If no matches are found from the count +1 position in the string, the method returns a one-element array that contains the input string. Если найдено одно или несколько совпадений, первый элемент возвращаемого массива содержит первую часть строки из первого символа до одного символа перед совпадением. If one or more matches are found, the first element of the returned array contains the first portion of the string from the first character up to one character before the match.

Если несколько совпадений находятся рядом друг с другом, а число найденных совпадений не count меньше, то в массив вставляется пустая строка. If multiple matches are adjacent to one another and the number of matches found is at least two less than count , an empty string is inserted into the array. Аналогично, если найдено соответствие в startat , которое является первым символом в строке, первый элемент возвращаемого массива является пустой строкой. Similarly, if a match is found at startat , which is the first character in the string, the first element of the returned array is an empty string. Таким образом, пустые строки, являющиеся результатом смежных совпадений, учитываются при определении того, равно count ли число сопоставленных подстрок. That is, empty strings that result from adjacent matches are counted in determining whether the number of matched substrings equals count . В следующем примере регулярное выражение \d+ используется для поиска начальной позиции первой подстроки числовых символов в строке, а затем для разделения строки до трех раз, начиная с этой позиции. In the following example, the regular expression \d+ is used to find the starting position of the first substring of numeric characters in a string, and then to split the string a maximum of three times starting at that position. Так как шаблон регулярного выражения соответствует началу входной строки, возвращаемый массив строк состоит из пустой строки, алфавитной строки из пяти символов и оставшейся части строки. Because the regular expression pattern matches the beginning of the input string, the returned string array consists of an empty string, a five-character alphabetic string, and the remainder of the string,

Если в регулярном выражении используются скобки записи, любой захваченный текст включается в массив разделенных строк. If capturing parentheses are used in a regular expression, any captured text is included in the array of split strings. Однако все элементы массива, содержащие захваченный текст, не учитываются при определении того, достигнуто count ли количество совпадений. However, any array elements that contain captured text are not counted in determining whether the number of matches has reached count . Например, разбиение строки «» Apple-Априкот-Плам-груш-граната-ананас-печь «в максимум четыре подстроки, начиная с символа 15 в строке, приводит к последующему массиву из семи элементов, как показано в приведенном ниже коде. For example, splitting the string ‘»apple-apricot-plum-pear-pomegranate-pineapple-peach» into a maximum of four substrings beginning at character 15 in the string results in a seven-element array, as the following code shows.

Однако если шаблон регулярного выражения включает несколько наборов скобок записи, поведение этого метода зависит от версии .NET Framework. However, when the regular expression pattern includes multiple sets of capturing parentheses, the behavior of this method depends on the version of the .NET Framework. В .NET Framework 1,0 и 1,1, если совпадение не найдено в первом наборе скобок записи, записанный текст из дополнительных скобок записи не включается в возвращаемый массив. In .NET Framework 1.0 and 1.1, if a match is not found within the first set of capturing parentheses, captured text from additional capturing parentheses is not included in the returned array. Начиная с .NET Framework 2,0, весь захваченный текст также добавляется в возвращаемый массив. Starting with the .NET Framework 2.0, all captured text is also added to the returned array. Например, следующий код использует два набора скобок записи для извлечения отдельных слов в строке. For example, the following code uses two sets of capturing parentheses to extract the individual words in a string. Первый набор скобок записи захватывает дефис, а второй набор захватывает вертикальную линию. The first set of capturing parentheses captures the hyphen, and the second set captures the vertical bar. Если пример кода компилируется и запускается под .NET Framework 1,0 или 1,1, он исключает символы вертикальной черты. Если он компилируется и запускается в .NET Framework 2,0 или более поздних версиях, он включает их. If the example code is compiled and run under the .NET Framework 1.0 or 1.1, it excludes the vertical bar characters; if it is compiled and run under the .NET Framework 2.0 or later versions, it includes them.

Если регулярное выражение может соответствовать пустой строке, будет Split разделять строку на массив односимвольных строк, так как разделитель пустых строк можно найти в каждом расположении. If the regular expression can match the empty string, Split will split the string into an array of single-character strings because the empty string delimiter can be found at every location. В следующем примере строка «символы» разбивается на столько элементов, сколько содержит входная строка, начиная с символа «a». The following example splits the string «characters» into as many elements as the input string contains, starting with the character «a». Поскольку строка NULL соответствует концу входной строки, в конце возвращаемого массива вставляется пустая строка. Because the null string matches the end of the input string, a null string is inserted at the end of the returned array.

HackWare.ru

Этичный хакинг и тестирование на проникновение, информационная безопасность

Регулярные выражения в PHP (ч. 2)

Оглавление

Первая часть:

Вторая часть:

Рекомендуется начать знакомство с регулярными выражениями в PHP с первой части.

Общие типы символов

Теперь мы опять вернёмся к синтаксису, который может использоваться при написании регулярных выражений. В отличие от ранее рассмотренных основ, описанное ниже является более сложным и применяется реже, либо может быть описано с помощью уже рассмотренного синтаксиса.

Например, далее рассмотрены способы указания общего типа символов — некоторые из этих способов записи являются альтернативным синтаксисом к уже рассмотренным. Допустим если мы хотим указать в регулярном выражении «любая цифра», то мы можем использовать [0-9]. Также имеется ещё один вариант записи с помощью экранирующих последовательностей. «Любая десятичная цифра» в них обозначается как \d.

Экранирующие последовательности — это набор символов, которые начинаются с обратного слэша \ и, следовательно, которые теряют своё буквальное значение, а начинают иметь специальное значение. Получается, что для специальных символов обратный слэш отключает их специальное значение, а для обычных букв и цифр он включает специальное значение (если оно предусмотрено).

Среди экранирующих последовательностей есть элементы синтаксиса, который невозможно передать иным способом. Примеры будут показаны далее.

Общие типы символов обозначаются так:

\d

любая десятичная цифра

\D

любой символ, кроме десятичной цифры

\h

любой горизонтальный пробельный символ

\H

любой символ, не являющийся горизонтальным пробельным символом

\s

любой пробельный символ

\S

любой непробельный символ

\v

любой вертикальный пробельный символ

\V

любой символ, не являющийся вертикальным пробельным символом

\w

Любой символ, образующий «слово»

\W

Любой символ, не образующий «слово»

Каждая пара таких специальных последовательностей делит полное множество всех символов на два непересекающихся множества. Любой символ соответствует одному и только одному множеству из пары.

Следующие символы считаются как «пробельные»: HT (9), LF (10), FF (12), CR (13), и пробел (32). Тем не менее, если идет локале-зависимый поиск, и произойдет совпадение с символами в диапазоне 128-255, они также будут восприняты как пробельные, например NBSP (A0).

Символ, образующий «слово» — это произвольная цифра, буква или символ подчеркивания, проще говоря, любой символ, который может являться частью «слова» в Perl. Определение букв и цифр управляется символьными таблицами, с которыми была собрана PCRE. И, как следствие, эти наборы могут отличаться в различных локализированных дистрибутивах. Например, в локали «fr» (Франция) некоторые символы с кодом выше 128 используются для записи ударных символов и, соответственно, соответствуют маске \w.

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

У этих символов может быть весьма полезное применение. Давайте вспомним (чуть переделанное) регулярное выражение для вывода HTML тэга всех заголовков вместе с конечным тегом, а также вместе с самим содержанием заголовка:

Используя уже известный код:

я получил вот такой результат:

Найдено всего 15 совпадений, хотя мы помним, что на этой странице заголовков намного больше. Дело в том, что найдены только заголовки, которые в HTML коде записаны в одну строку, например так:

А если запись разбита на несколько строк, например так:

то такие заголовки найдены не были.

Проблема не в каких-то ограничениях регулярных выражений — в PHP анализ текста происходит именно целиком, то есть даже если текст состоит из нескольких строк, в PHP он анализируется за раз, без разбития на строки.

Проблема в нашем регулярном выражении, которое мы написали — мы не указали, что после открывающего тэга заголовка могут идти пробелы. Затем после содержимого заголовка также могут идти пробелы. Давайте составим новое регулярное выражение, с учётом этого. Любые пробельные символы обозначаются как \s. Их может не быть вовсе, а может быть несколько, поэтому в качестве квантора нужно использовать звёздочку, получаем \s*. Эту конструкцию вставляем два раза: 1) между открывающим HTML тэгом и содержимым заголовка; 2) между концом содержимого заголовка и закрывающим HTML тэгом.

Получаем такое регулярное выражение:

В результате находим 51 заголовок — видимо, это все заголовки анализируемой страницы, среди них как написанный в одну строку, так и многострочные.

В подобных случаях также можно использовать модификатор регулярного выражения s. Подробности и примеры смотрие в статье «Поиск по нескольким строкам в PHP с функциями preg_match_all и preg_match».

Следующие два раздела (непечатные символы и определение формальных утверждений) — нечасто применимы, поэтому если вы в них не разобрались, то просто переходите к последующим параграфам.

Непечатные символы в видимой форме в описании шаблона

В PCRE нет ограничений на использование непечатных символов (исключая бинарный ноль, который интерпретируется как конец шаблона), тем не менее, при редактировании программного кода в каком-либо текстовом редакторе гораздо удобнее использовать следующие комбинации, чем реальные символы, которые они представляют:

\a

символ оповещения, сигнал, (BEL, шестнадцатеричный код 07)

\cx

«Ctrl+x«, где x — произвольный символ

\e

escape (шестнадцатеричный код 1B)

\f

разрыв страницы (шестнадцатеричный код 0C)

\n

перевод строки (шестнадцатеричный код 0A)

символ со свойством xx, подробнее смотрите свойства unicode

символ без свойства xx, подробнее смотрите свойства unicode

\r

возврат каретки (шестнадцатеричный код 0D)

\R

разрыв строки: совпадает с \n, \r и \r\n

\t

табуляция (шестнадцатеричный код 09)

\xhh

символ с шестнадцатеричным кодом hh

\ddd

символ с восьмеричным кодом ddd, либо ссылка на подмаску

Если быть более точным, комбинация «\cx» интерпретируется следующим образом: если «x» — символ нижнего регистра, он преобразуется в верхний регистр. После этого шестой бит символа (шестнадцатеричный код 40) инвертируется. Таким образом «\cz» интерпретируется как шестнадцатеричное значение 1A, в то время как «\c<" получает шестнадцатеричное значение 3B, а "\c;" - 7B.

После «\x» считываются еще две шестнадцатеричные цифры (они могут быть записаны в нижнем или верхнем регистре). В режиме UTF-8, разрешается использование «\x<. >«, где содержимое скобок является строкой из шестнадцатеричных цифр. Она интерпретируется как символ UTF-8 character с кодом, совпадающим с данным шестнадцатеричным числом. Исходная шестнадцатеричная экранирующая последовательность, \xhh, совпадает с двухбайтным UTF-8 символом, если его значение превышает 127.

После «\0» считываются две восьмеричные цифры. Если в записи менее двух цифр, будут использованы все фактически присутствующие цифры. Таким образом, последовательность «\0\x\07» будет интерпретирована как два бинарных нуля, за которыми следует символ оповещения (звонок). В случае, если вы используете представление числа в восьмеричном коде, убедитесь, что за начальным нулем следуют две значащие цифры.

Обработка обратного слеша, за которым следует ненулевая цифра, несколько сложнее. Вне символьного класса PCRE воспринимает обратный слеш и следующие за ним цифры как десятичное число. Если полученное значение меньше десяти, либо если шаблон содержит по меньшей мере такое же количество предшествующих текущей позиции подмасок, вся конструкция интерпретируется как ссылка на подмаску. Более детальное описание будет приведено ниже при обсуждении механизма работы подмасок.

Внутри символьного класса, либо если полученное значение больше 9 и соответствующее количество предшествующих подмасок отсутствует, PCRE считывает до трех восьмеричных цифр, следующих за обратным слешем, и генерирует один байт из последних 8-ми значащих битов полученного значения. Все последующие цифры обозначают себя же. Например:

\040

еще один способ записи пробела

\40

то же самое в случае, если данной записи предшествует менее сорока подмасок

\7

всегда интерпретируется как ссылка на подмаску

\11

может быть как обратной ссылкой, так и альтернативной записью символа табуляции

\011

всегда интерпретируется как символ табуляции

\0113

символ табуляции, за которым следует цифра «3»

\113

интерпретируется как символ с восьмеричным кодом 113 (так как ссылок на подмаски не может быть более чем 99)

\377

байт, всецело состоящий из единичных битов

\81

либо обратная ссылка, либо бинарный ноль, за которым следуют цифры «8» и «1»

Следует помнить, что восьмеричные значения, превышающие 100, следует писать без лидирующего нуля, так как читается не более трех восьмеричных цифр.

Все последовательности, определяющие однобайтное значение, могут встречаться как внутри, так и вне символьных классов. Кроме того, внутри символьного класса запись «\b» интерпретируется как символ возврата (‘backspace’, шестнадцатеричный код 08). Вне символьного класса она имеет другое значение (какое именно, описано ниже).

Определение формальных утверждений

Ещё одно использование обратного слеша — определение некоторых формальных утверждений, описывающих условия касательно месторасположения особых позиций в строке и совершенно не затрагивающих сами символы. Использование подмасок как более сложных формальных утверждений описано далее. Такими управляющими последовательностями являются:

\b

\B

не является границей слова

\A

начало данных (независимо от многострочного режима)

\Z

конец данных либо позиция перед последним переводом строки (независимо от многострочного режима)

\z

конец данных (независимо от многострочного режима)

\G

первая совпадающая позиция в строке

Описанные выше последовательности не могут встречаться в символьных классах (исключая комбинацию «\b«, которая внутри класса означает символ возврата ‘backspace’).

Границей слова считается такая позиция в строке, в которой из текущего и предыдущего символа только один соответствует \w или \W (т.е. один из них соответствует \w, а другой \W). Начало или конец строки также соответствуют границе слова в случае, если первый или, соответственно, последний символ совпадает с \w.

Специальные последовательности \A, \Z и \z отличаются от общеупотребляемых метасимволов начала строки ‘^‘ и конца строки ‘$‘ (описанных в разделе якоря первой части) тем, что они всегда совпадают либо в самом начале либо в самом конце строки. На них никак не влияют опции m (PCRE_MULTILINE) и D (PCRE_DOLLAR_ENDONLY). Разница между \Z и \z в том, что \Z соответствует позиции перед последним символом в случае, если последний символ — перевод строки, кроме самого конца строки. В то время, как \z соответствует исключительно концу данных.

Утверждение \G является истинным только в том случае, если текущая проверяемая позиция находится в начале совпадения, указанного параметром offset функции preg_match(). Она отличается от \A при ненулевом значении параметра offset.

\Q и \E могут быть использованы для игнорирования метасимволов регулярных выражений в шаблоне. Например: \w+\Q.$.\E$ совпадет с один или более символов, составляющих «слово»,за которыми следуют символы .$. и якорь в конце строки.

Последовательность \K может быть использована для сброса начала совпадения. Например, шаблон foo\Kbar совпадет с «foobar», но сообщит о том, что совпал только с «bar». Использование \K не мешает установке подмасок. Например, если шаблон (foo)\Kbar совпадет со строкой «foobar», первой подмаской все равно будет являться «foo».

POSIX нотация для символьных классов

Perl поддерживает нотацию POSIX для символьных классов. Это включает использование имен, заключенных в [: и :], в свою очередь заключенных в квадратные скобки. PCRE также поддерживает эту запись. Например, [01[:alpha:]%] совпадет с «0», «1», любым алфавитным символом или «%«. Поддерживаются следующие имена классов:

alnum буквы и цифры
alpha буквы
ascii символы с кодами 0 — 127
blank только пробел или символ табуляции
cntrl управляющие символы
digit десятичные цифры (то же самое, что и \d)
graph печатные символы, исключая пробел
lower строчные буквы
print печатные символы, включая пробел
punct печатные символы, исключая буквы и цифры
space пробельные символы(почти то же самое, что и \s)
upper прописные буквы
word символы «слова» (то же самое, что и \w)
xdigit шестнадцатеричные цифры

Класс пробельных символов (space) — это горизонтальная табуляция (HT, 9), перевод строки (LF, 10), вертикальная табуляция (VT, 11), разрыв страницы (FF, 12), возврат каретки (CR, 13) и пробел (32). Учтите, что этот список включает вертикальную табуляцию (VT, код 11). Это отличает «space» от \s, который не включает этот символ (для совместимости с Perl).

Название word — это расширение Perl, а blank — расширение GNU, начиная с версии Perl 5.8. Другое расширение Perl — это отрицание, которое указывается символом ^ после двоеточия. Например, [12[:^digit:]] совпадет с «1», «2», или с любой не-цифрой.

В режиме UTF-8, символы со значениями, превышающими 128, не совпадут ни с одним из символьных классов POSIX. Начиная с PHP 5.3.0 и libpcre 8.10 некоторые символьные классы изменены, чтобы использовать свойства символов Unicode, в этом случае упомянутое ограничение не применяется. Читайте руководство PCRE(3) для подробностей.

Подмаски

Подмаска — это часть регулярного выражения, которая участвует в поиске. Подмаска может выполнять несколько функций:

1) если была найдена строка, соответствующая целому регулярному выражению, то в результаты поиска будут возвращены две строки: во-первых, соответствующая всему регулярному выражению, и, во-вторых, соответствующая подмаске

2) найденная в подмаске строка может вновь использоваться в регулярном выражении в качестве обратной ссылке (о них позже)

Подмаски в регулярном выражении выделяются скобками. В регулярном выражении может быть более чем одна подмаска, в этом случае они нумеруются слева направо.

Подмаски могут быть вложенными одна в другую.

При использовании функции preg_match_all возвращается массива, где в качестве первого элемента (с индексом 0) возвращается массив с найденными значениями строк. Если указаны подмаски, то в качестве второго элемента возвращаемого массива (с индексом 1) будет массив с найденными строками, соответствующими первой подмаске. Если используется две подмаски, то будет возвращён ещё один массив и так далее для каждой последующей подмаске.

Как мы помним из первой части, описывающий синтаксис регулярных выражений, скобки имеют и другое значение: или использовании оператора | (ИЛИ) они ограничивают варианты альтернатив друг от друга. Например, шаблон cat(aract|erpillar|) соответствует одному из слов «cat», «cataract» или «caterpillar». Без использования скобок он соответствовал бы строкам «cataract», «erpillar» или пустой строке.

То есть скобки выполняют одновременно две функции.

На самом деле выполнение одновременно двух функций не всегда удобно. Бывают случаи, когда необходима группировка альтернатив без захвата строки. В случае, если после открывающей круглой скобки следует «?:«, захват строки не происходит, и текущая подмаска не нумеруется. Например, если строка «the white queen» сопоставляется с шаблоном the ((?:red|white) (king|queen)), будут захвачены подстроки «white queen» и «queen», и они будут пронумерованы 1 и 2 соответственно. Максимальное количество захватывающих подмасок — 65535. Такие большие шаблоны могут не скомпилироваться, в зависимости от настроек libpcre.

В случае, если в незахватывающей подмаске необходимо указать дополнительные опции, можно воспользоваться удобным сокращением: символ, обозначающий устанавливаемую опцию помещается между «?» и «:«. Таким образом, следующие два шаблона

соответствуют одному и тому же набору строк. Поскольку альтернативные версии берутся слева направо, и установленные опции сохраняют своё действие до конца подмаски, опция, установленная в одной ветке, также имеет эффект во всех последующих ветках. Поэтому приведенные выше шаблоны совпадают как с «SUNDAY», так и с «Saturday».

Также можно использовать именованные подмаски с помощью синтаксиса (?P pattern). Эта подмаска будет индексирована в массиве совпадений кроме обычного числового индекса, еще и по имени name. В PHP 5.2.2 было добавлено два альтернативных синтаксиса: (? pattern) и (?’name’pattern).

Иногда бывает необходимо иметь несколько совпадений, исключающих друг друга. Обычно, каждое такое совпадение получает свой собственный номер, даже если шаблон позволяет совпасть только одному из них. Синтаксис (?| позволяет обойти это поведение и убрать дублирующиеся номера. Рассмотрим следующее регулярное выражение, сопоставленное со строкой Sunday:

Здесь Sun сохраняется в ссылке 2, тогда как ссылка 1 пуста. Если же совпадет Sat, то она будет помещена в ссылку 1, а ссылка 2 вообще не будет существовать. Использование (?| в шаблоне решает эту проблему:

В этом шаблоне обе подмаски Sun и Sat будут сохранены под номером 1.

Обратные ссылки в PHP

Как мы только что выяснили, строки, найденные в подмасках, возвращаются вместе с основными найденными строками. Но их можно использовать в самих регулярных выражениях.

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

Однако, в случае, если следующее за обратным слешем число меньше 10, оно всегда интерпретируется как обратная ссылка, и приводит к ошибке только в том случае, если нет соответствующего числа открывающих скобок. Другими словами, открывающие скобки не обязаны предшествовать ссылке для чисел меньше 10. «Упреждающая обратная ссылка» может иметь смысл, если используется повторение и более поздняя подмаска участвует в ранней итерации. Более детальную информацию об обработке цифр после обратного слеша можно найти в разделе «Обратный слеш».

Обратная ссылка сопоставляется с частью строки, захваченной соответствующей подмаской, но не с самой подмаской. Таким образом шаблон (sens|respons)e and \1ibility соответствует «sense and sensibility», «response and responsibility», но не «sense and responsibility». В случае, если обратная ссылка обнаружена во время регистрозависимого поиска, то при сопоставлении обратной ссылки регистр также учитывается. Например, ((?i)rah)\s+\1 соответствует «rah rah» и «RAH RAH», но не «RAH rah», хотя сама подмаска сопоставляется без учета регистра.

На одну и ту же подмаску может быть несколько ссылок. Если подмаска не участвовала в сопоставлении, то сопоставление со ссылкой на нее всегда терпит неудачу. Например, шаблон (a|(bc))\2 терпит неудачу, если находит соответствие с «a» раньше, чем с «bc». Поскольку может быть до 99 обратных ссылок, все цифры, следующие за обратным слешем, рассматриваются как часть потенциальной обратной ссылки. Если за ссылкой должна следовать цифра, необходимо использовать ограничитель. В случае, если указан флаг x (PCRE_EXTENDED), ограничителем может быть любой пробельный символ. В противном случае можно использовать пустой комментарий.

Ссылка на подмаску, внутри которой она расположена, всегда терпит неудачу, если это первое сопоставление текущей подмаски. Например, шаблон (a\1) не соответствует ни одной строке. Но все же такие ссылки бывают полезны в повторяющихся подмасках. Например, шаблон (a|b\1)+ совпадает с любым количеством «a», «aba», «ababaa». При каждой итерации подмаски обратная ссылка соответствует той части строки, которая была захвачена при предыдущей итерации. Чтобы такая конструкция работала, шаблон должен быть построен так, чтобы при первой итерации сопоставление с обратной ссылкой не производилось. Этого можно достичь, используя альтернативы (как в предыдущем примере), либо квантификаторы с минимумом, равным нулю.

Начиная с PHP 5.2.2, управляющая последовательность \g может быть использована для абсолютных и относительных ссылок на подмаски. После этой последовательности должно быть указано беззнаковое или отрицательное число, при желании заключенное в фигурные скобки. Последовательности \1, \g1 и \g эквивалентны друг другу. Использование этого шаблона с беззнаковым числом поможет избежать двусмысленности, присущей числам после обратного слеша. Это также помогает отличить обратные ссылки от символов в восьмеричном формате, а также упрощает запись числового литерала сразу после обратной ссылки, например, \g<2>1.

Использование отрицательных чисел с \g полезно при использовании относительных ссылок. Например, (foo)(bar)\g соответствует «foobarbar», а (foo)(bar)\g соответствует «foobarfoo». Это также может быть полезно в длинных шаблонах, в качестве альтернативы отслеживания числа подмасок, на которые можно ссылаться в последующей части шаблона.

Указать обратную ссылку на именованную подмаску можно с помощью (?P=name) или, начиная с PHP 5.2.2, \k или \k’name‘. Кроме того, в PHP 5.2.4 была добавлена поддержка \k> и \g>, а в PHP 5.2.7 для \g и \g’name’.

К примеру, я хочу найти строки, состоящие из пяти любых, но одинаковых цифр, например, «11111», «22222» и так далее, в этом случае я могу написать следующее регулярное выражение:

Как мы рассмотрели чуть выше, экранирующая последовательность \d обозначает любую цифру. Для того, чтобы найденную строку можно было использовать в качестве обратной ссылке, мы заключаем эту часть регулярного выражения в круглые скобки. То есть получается, что мы создаём подмаску в регулярном выражении. Затем идёт обратный слэш \ с цифрой 1 — это и есть обратная ссылка. То есть, что бы ни было найдено в первой подмаске, его значение будет помещено в обратную ссылку \1. Затем ещё идут три таких же обратных ссылки. Получается что регулярное выражение ищет любую цифру, за которой ещё четыре раза идёт эта же самая цифра.

Для поиска возьмём строку:

даст следующий результат:

В первый элемент массива помещён массив с найденными строками из пяти цифр. Во второй элемент массив помещён массив, соответствующий подмаскам — то есть одиночным цифрам. Но взяты не любые одиночные цифры — совпавшие значения подмасок взяты только в тех случаях, когда весь шаблон совпал со строкой.

Рассмотрим более практический пример. Допустим мы хотим найти в HTML коде все пары тэгов: открывающий и закрывающий тэг, между которыми идёт какой-либо текст. Есть исключения (например,
, и так далее) — но не будем их рассматривать, чтобы не усложнять пример.

Тэг абзаца выглядит примерно так:

Тэг раздела страницы:

Как мы видим, в угловые скобки помещено название тэга, которое представляет собой одну или более маленьких букв. Закрывающим тэгом является эта же самая конструкция, с этим же самым названием тэга, но перед названием добавляется слэш /.

Любая буква в угловых скобках обозначается так:

Чтобы создать обратную ссылку, поместим ту часть выражения, которая обозначает буквы, в круглые скобки:

Закрывающим тэгом будет обратная ссылка, содержащая найденное название тэга, помещённая между , то есть:

Поскольку в качестве разделителя используется слэш, то тот слэш, который означает «буквальный слэш» нужно экранировать, чтобы он потерял своё специальное значение и стал трактоваться как буквальный символ, получаем:

Составленное регулярное выражение будет соответствовать тэгам в следующем написании:

Но нужно помнить, что между тэгами почти всегда есть какой-то текст. В качестве этого тэга может быть что угодно, кроме символа , поскольку этот символ означает завершение открывающего тэга, поэтому значение «пусто, либо пробел а затем любые символы кроме > любое количество раз» на языке регулярных выражений записывается так:

Помещаем эту конструкцию в ранее составленное регулярное выражение в то место, где могут быть атрибуты:

Функции PHP для поиска и замены по регулярному выражению

Рассмотренные ранее функции ищут строки по регулярному выражению (preg_match_all), либо проверяют, строку на соответствие регулярному выражению (preg_match). В случае, если нужно не просто найти строку, но и заменить её, используются следующие функции:

  • preg_filter — Производит поиск и замену по регулярному выражению
  • preg_replace_callback_array — Выполняет поиск и замену по регулярному выражению с использованием функций обратного вызова
  • preg_replace_callback — Выполняет поиск по регулярному выражению и замену с использованием callback-функции
  • preg_replace — Выполняет поиск и замену по регулярному выражению

В результате работы функции preg_replace, если найдены совпадения, возвращается новая версия subject, иначе subject возвращается нетронутым. Функция preg_filter() идентична функции preg_replace() за исключением того, что возвращает только те значения (возможно, преобразованные), в которых найдено совпадение. Подробнее о работе функций читайте по приведённым выше ссылкам.

Функция preg_replace_callback позволяет делать интеллектуальную замену. Её суть заключается в том, что не просто выполняется замена найденной строки, а вызывается функция, которой передаётся совпавшая строка, и эта функция уже и возвращает строку с заменой. Вместо элементарной замены, функция может, например, делать дополнительную проверку полученных данных и уже на основе принятого решения выполнять ту или иную замену. Можно установить счётчик и делать замену в каждом n-ной совпавшей строке — например, в каждой третьей или каждой десятой. Можно пронумеровать найденные строки и делать любые другие изменения, которые не ограничиваются обычным поиском и заменой на фиксированную строку.

Пример использование функции preg_replace_callback:

В этом примере из монотонной строки будут выбраны имена и каждое имя будет напечатано по отдельности. Для третьего имени будет написано, что это третье имя, для каждого десятого имени будет написано, что его номер кратен 10:

Пример моего реального недавнего использования функции preg_replace_callback на практике — добавления рекламы в каждый десятый комментарий — с её помощью очень легко реализовать подобную логику.

Другие функции PHP для работы с регулярными выражениями

  • preg_last_error — Возвращает код ошибки выполнения последнего регулярного выражения PCRE
  • preg_quote — Экранирует символы в регулярных выражениях
  • preg_split — Разбивает строку по регулярному выражению

Когда не нужно использовать регулярные выражения

Не используйте функцию preg_match(), если необходимо проверить наличие подстроки в заданной строке. Используйте для этого strpos() поскольку она выполнит эту задачу гораздо быстрее.

Если вам не нужна мощь регулярных выражений, то вместо preg_split вы можете выбрать более быстрые (хоть и простые) альтернативы наподобие explode() или str_split().

PHP: строку в массив по разделителю

Для того, чтобы преобразовать строку в массив по разделителю, можно использовать функцию explode()
Необходимые параметры: разделитель и строка.

Простой пример кода из документации:

Разбить строку на массив по регулярному выражению

Если возможностей explode() недостаточно, то можно использовать более мощную функцию: preg_split (). Она позволяет разбить строку не по фиксированному набору символов, а по регулярному выражению.

Пример из документации:

Преобразовать строку в массив по количеству символов

Функция str_split() преобразует строку в массив, разбивая ее на элементы с заданным количеством символов. Хотите узнать как ее использовать? Посмотрите документацию.

Разбиение строки на токены

Есть еще функция strtok() . Она позволит задать набор из нескольких символов-разделителей, для разделения строки по словам: читать подробнее про strok.

Илон Маск рекомендует:  Элемент xslif улучшение внешнего вида таблиц xml xslt
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL