Чтение онлайн

на главную

Жанры

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

Часть IV

Библиотеки для разработки

Глава 23

Сопоставление строк

Осуществлять сравнение строк можно не только с помощью функции

strcmp
или даже
strncmp
. Linux предлагает несколько общих функций сопоставления строк, использование которых позволяет упростить решение задач программирования. Мы рассмотрим сначала самые простые примеры, а затем перейдем к более сложным.

23.1. Универсализация произвольных строк

В главе 14 мы говорили о том, как с помощью функции

glob
производится универсализация имен файлов, однако пользователи, знакомые с возможностями универсализации,
нередко пытаются применить их и к другим разновидностям строк. Функция
fnmatch
позволяет применять правила универсализации в отношении произвольных строк:

#include <fnmatch.h>

int fnmatch(const char * pattern, const char * string, int flags);

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

flags
.

*
Соответствует любой строке, включая пустую.
?
Соответствует любому одиночному символу.
[
Начинает список символов для сопоставления или, если следующим символом является
^
, то список символов для несовпадения. Весь список может совпадать, или не совпадать с одним символом. Список заканчивается знаком
]
.
\
Следующий символ будет интерпретироваться как литерал, а не как специальный символ.

На результаты универсализации влияет аргумент

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

FNM_NOESCAPE
Обработка символа
\
как обычного, а не специального символа.
FNM_PATHNAME
Символы
/
в строке
string
не сопоставляются с последовательностью
*
,
?
, или даже
[/]
в шаблоне
pattern
; сопоставление производится только с литералом, а не специальным символом
/
.
FNM_NOESCAPE
Первый символ
.
в шаблоне pattern соответствует символу
.
в строке
string
только в том случае, если он является первым символом в строке
string
или если задано значение
FNM_PATHNAME
, а символ
.
в
string
непосредственно следует за символом
\
.

Функция

fnmatch
возвращает нулевое значение, если шаблон соответствует строке,
FNM_NOMATCH
, если шаблон не соответствует строке, или другое неопределенное значение в случае возникновения ошибки.

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

fnmatch
вы можете посмотреть в программе, приведенной в разделе 14.7.3 главы 14, в которой эта функция используется как часть простой реализации команды
find
.

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

Регулярные выражения, используемые в программах

sed
,
awk
,
grep
,
vi
, а также во множестве других программ Unix, со временем приобрели большое значение в среде программирования Unix.
Регулярные выражения можно применять и при написании программ на языке С. В этом разделе будет рассказано об их использовании и будет предложен пример простой программы синтаксического анализа файла, построенной на этих функциях.

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

Существуют две разновидности регулярных выражений: базовые регулярные выражения (basic regular expression — BRE) и расширенные регулярные выражения (extended regular expression — ERE). Они соответствуют (в первом приближении) командам grep и egrep. Описание каждой разновидности регулярных выражений можно найти на man-странице grep, в стандарте POSIX.2 (IEEE, 1993), в [32], а также в других источниках, поэтому здесь мы не станем описывать их синтаксис, а рассмотрим только интерфейс функции, с помощью которой вы сможете применять регулярные выражения в своих программах.

23.2.2. Сопоставление с регулярными выражениями

Стандарт POSIX определяет четыре функции обработки регулярных выражений.

#include <regex.h>

int regcomp(regex_t *preg, const char * regex, int cflags);

int regexec(const regex_t *preg, const char * string, size_t nmatch,

 regmatch_t pmatch[], int eflags);

void regfree(regex_t *preg);

size_t regerror(int errcode, const regex_t *preg, char * errbuf,

 size_t errbuf_size);

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

regcomp
. Аргумент
regex_t *preg
указывает на область хранения регулярного выражения. Чтобы каждое регулярное выражение было доступно одновременно, для него потребуется отдельный аргумент
regex_t
. Структура
regex_t
включает только один важный член,
re_nsub
, который определяет количество подвыражений в регулярном выражении, заключенных в скобки. Рассмотрим оставшуюся часть непрозрачной структуры.

Аргумент

сflags
определяет варианты интерпретации регулярного выражения
regex
. Он может иметь нулевое значение или быть любой комбинацией перечисленных ниже значений, объединенных битовым "ИЛИ".

REG_EXTENDED
Вместо синтаксической структуры BRE будет использоваться структура ERE.
REG_ICASE
Не будет учитываться регистр.
REG_NOSUB
Не будут выделяться подстроки. Функция
regexec
будет игнорировать аргументы
nmatch
и
pmatch
.
REG_NEWLINE
Если значение
REG_NEWLINE
не будет задано, то символ новой строки будет обрабатываться точно так же, как и любой другой символ. Символы
^
и
$
соответствуют только началу и концу всей строки, а не соседним символам новой строки. Если значение
REG_NEWLINE
будет задано, то результат будет таким же, как и в случае использования
grep
,
sed
и других стандартных системных инструментальных средств; символ ^ осуществляет привязку к началу строки и символу, следующему после символа новой строки (фактически он соответствует строке нулевой длины, следующей за символом новой строки);
$
осуществляет привязку к концу строки и символу, следующему после символа новой строки (фактически, он соответствует строке нулевой длины, предшествующей символу новой строки); символ
.
не соответствует символу новой строки.
Поделиться:
Популярные книги

Замуж второй раз, или Ещё посмотрим, кто из нас попал!

Вудворт Франциска
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Замуж второй раз, или Ещё посмотрим, кто из нас попал!

Протокол "Наследник"

Лисина Александра
1. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Протокол Наследник

Сердце Дракона. Том 11

Клеванский Кирилл Сергеевич
11. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
6.50
рейтинг книги
Сердце Дракона. Том 11

Вперед в прошлое!

Ратманов Денис
1. Вперед в прошлое
Фантастика:
попаданцы
5.00
рейтинг книги
Вперед в прошлое!

Шесть принцев для мисс Недотроги

Суббота Светлана
3. Мисс Недотрога
Фантастика:
фэнтези
7.92
рейтинг книги
Шесть принцев для мисс Недотроги

Хочу тебя любить

Тодорова Елена
Любовные романы:
современные любовные романы
5.67
рейтинг книги
Хочу тебя любить

Огни Аль-Тура. Желанная

Макушева Магда
3. Эйнар
Любовные романы:
любовно-фантастические романы
эро литература
5.25
рейтинг книги
Огни Аль-Тура. Желанная

Начальник милиции 2

Дамиров Рафаэль
2. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции 2

Мастер...

Чащин Валерий
1. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
6.50
рейтинг книги
Мастер...

Сумеречный стрелок 8

Карелин Сергей Витальевич
8. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Сумеречный стрелок 8

Я до сих пор не князь. Книга XVI

Дрейк Сириус
16. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я до сих пор не князь. Книга XVI

Обыкновенные ведьмы средней полосы

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Обыкновенные ведьмы средней полосы

Метаморфозы Катрин

Ром Полина
Фантастика:
фэнтези
8.26
рейтинг книги
Метаморфозы Катрин

Идеальный мир для Социопата

Сапфир Олег
1. Социопат
Фантастика:
боевая фантастика
рпг
постапокалипсис
6.17
рейтинг книги
Идеальный мир для Социопата