Роббинс Арнольд
Шрифт:
Флаги для сопоставления регулярных выражений с помощью
regexec
приведены в табл. 12.8. Таблица 12.8. Флаги дли
regexec
Константа | Значение |
---|---|
REG_NOTBOL | Оператор ^ (начало строки) не сопоставляется |
REG_NOTEOL | Оператор $ (конец строки) не сопоставляется |
Флаги
REG_NEWLINE
, REG_NOTBOL
и REG_NOTEOL
взаимодействуют друг с другом. Это немного запутано, поэтому мы будем продвигаться небольшими шажками. • Когда в
cflags
не включен REG_NEWLINE
, символ конца строки действует в качестве обычного символа. С ним может быть сопоставлен метасимвол '.
' (любой символ), а также дополненные списки символов ('[^...]
'). При этом $
не сопоставляется немедленно с началом вставленного символа новой строки, а ^
не сопоставляется немедленно с его концом. • Когда в
eflags
установлен REG_NOTBOL
, оператор ^
не соответствует началу строки. Это полезно, когда параметр string
является адресом символа в середине сопоставляемого текста. • Сходным образом, когда в
eflags
установлен REG_NOTEOL
, оператор $
не соответствует концу строки. • Когда в
cflags
включен REG_NEWLINE
, то: • Символ конца строки не соответствует '
.
' или дополненному списку символов. • Оператор
^
всегда соответствует положению непосредственно за вставленным символом конца строки независимо от установки REG_BOL
. • Оператор
$
всегда соответствует положению непосредственно перед вставленным символом конца строки независимо от установки REG_EOL
. Когда вы осуществляете построчный ввод/вывод, как в случае с
grep
, можно не включать REG_NEWLINE
в cflags
. Если в буфере несколько строк, и каждую из них нужно рассматривать как отдельную, с сопоставлением ^
и $
, тогда следует включить REG_NEWLINE
. Структура
regex_t
по большей части непрозрачна. Код уровня пользователя может исследовать лишь один член этой структуры; остальное предназначено для внутреннего использования процедурами регулярных выражений: typedef struct {
/* ...здесь внутренний материал... */
size_t re_nsub;
/* ...здесь внутренний материал... */
} regex_t;
В структуре
regmatch_t
есть по крайней мере два члена для использования кодом уровня пользователя: typedef struct {
/* ...здесь возможный внутренний материал... */
regoff_t rm_so; /* Смещение начала вложенной строки в байтах */
regoff_t rm_eo; /* Смещение первого байта после вложенной строки */
/* ...здесь возможный внутренний материал... */
} regmatch_t;
Как поле
re_nsub
, так и структура regmatch_t
предназначены для сопоставления вложенных выражений. Рассмотрим такое регулярное выражение: [:пробел:]]+([[:цифра:]]+)[[:пробел:]]+([[:буква:]])+
Каждое из двух вложенных выражений в скобках могут соответствовать одному или более символам. Более того, текст, соответствующий каждому вложенному выражению, может начинаться и заканчиваться в произвольных участках строки.
regcomp
устанавливает в поле re_nsub
число вложенных выражений в скобках внутри регулярного выражения, regexec
заполняет массив pmatch
структур regmatch_t
смещениями начальных и конечных байтов текста, соответствующих этим вложенным выражениям. Вместе эти данные позволяют заменять текст — удалять его или заменять другим текстом, точно так же, как в текстовом редакторе pmatch[0]
описывает часть строки, соответствующую всему регулярному выражению. Участок от pmatch[1]
до pmatch[preg->re_nsub]
описывает ту часть, которая соответствует каждому вложенному выражению в скобках. (Таким образом, вложенные выражения нумеруются начиная с 1.) Элементы rm_so
и rm_eo
не используемых элементов массива pmatch
установлены в -1. regexec
заполняет не более nmatch-1
элементов pmatch
; поэтому следует убедиться, что имеется по крайней мере на 1 элемент больше, чем в preg->re_nsub
. Наконец, флаг
REG_NOSUB
для regcomp
означает, что начальная и завершающая информация не нужна. Этот флаг следует использовать, когда эти сведения не нужны; это потенциально может довольно значительно повысить производительность regexec
. Другими словами, если все, что вам нужно знать, это «соответствует ли?», включите
REG_NOSUB
. Однако, если нужно также знать, «где находится соответствующий текст?», этот флаг следует опустить.