Olej писал(а):
Дело в том, что из нескольких вариантов реализации регулярных выражений в C, ни один не предусматривает работы с широкими локализованными символами wchar_t.
Вар.№4
Это широко используемый пакет (его библиотеки) — PCRE (Perl Compatible Regular Expressions). Для этого вы должны иметь установленным соответствующий
пакет (или установить его из репозитория своего дистрибутива):
Код: Выделить всё
$ dnf list pcre
Последняя проверка окончания срока действия метаданных: 0:00:15 назад, Thu Sep 8 19:12:56 2016.
Установленные пакеты
pcre.i686 8.39-2.fc23 @updates
pcre.x86_64 8.39-2.fc23 @updates
Для DEB дистрибутивов тоже не проблема найти и установить требуемые библиотеки (от дистрибутива к дистрибутиву могут варьироваться только наименования пакетов репозиториев), для примера, это в Mint 17.2:
Код: Выделить всё
$ apt show libpcre3
Пакет: libpcre3
...
Сопровождающий: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
...
Описание: поддержка регулярных выражений, совместимых с Perl5 (динамическая версия)
Библиотека предоставляет функции для работы с регулярными выражениями.
Синтаксис и семантика выражений сделаны максимально похожими на регулярные
выражения языка Perl 5.
Используя этот инструментарий приложение, подобное предыдущим, может быть сделано так:
Код: Выделить всё
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <pcre.h>
int main( int argc, char *argv[] ) {
#define SIZE 80
char buf[ SIZE ] = "test test test test ", // errbuf[ SIZE ] = "",
pattern[ SIZE ] = "s";
#define MATCHSIZE 20
const unsigned char *locale_tables = pcre_maketables();
if( argc > 1 ) strncpy( pattern, argv[ 1 ], SIZE - 1 );
int options = 0;
const char *error;
int erroffset;
pcre *re = pcre_compile( (char*)pattern, options, &error, &erroffset, locale_tables );
if( !re ) {
printf( "pattern error: %s\n", error );
return 1;
}
int count = 0;
int ovector[ MATCHSIZE * 2 ];
while( fgets( buf, sizeof( buf ) - 1, stdin ) ) {
if( buf[ strlen( buf ) - 1 ] == '\n') buf[ strlen( buf ) - 1 ] = '\0';
if( 0 == strlen( buf ) ) continue;
if( argc > 1 ) printf( "'%s' ->\n", buf );
count = pcre_exec( re, NULL, (char*)buf, strlen( buf ), 0, 0, ovector, MATCHSIZE );
if( count < 0 ) {
printf( "no match\n" );
continue;
}
for( int c = 0; ( c < 2 * count ) && ( ovector[ c ] >= 0 ); c += 2 ) {
printf( "%d/%d : ", ovector[ c ], ovector[ c + 1 ] );
for( int i = ovector[ c ]; i < ovector[ c + 1 ]; i++ )
printf( "%c", buf[ i ] );
printf( "\n" );
}
}
return 0;
}
Здесь та же история, что и ранее: сначала скомпилировать шаблон регулярного выражения, а затем сколько угодно раз сопоставлять его с входными строками. Глубоко в недрах документации библиотеки утверждается, что если последний параметр вызова компиляции pcre_compile() равен NULL, то используется собственной таблицей символов pcre_default_tables, которая определена в исходном файле chartables.c и вкомпилирована в модуль библиотеки. Но эту таблицу можно изменить вызовом pcre_maketables(), которая не предусматривает параметров и использует текущую установленную локаль.
Для сборки обязательна библиотека (и в ряде дистрибутивов её лучше указать в командной строке после файла исходного кода … на самом деле — после объектного файла):
Проверяем то, что из этого получилось:
Код: Выделить всё
$ ./regex3 "Ё"
это Ёлка
'это Ёлка' ->
7/9 : Ё
а это ёлка
'а это ёлка' ->
no match
31.12.2016 NewYear - Ёлка
'31.12.2016 NewYear - Ёлка' ->
21/23 : Ё
^C
(Литеры 'Ё' и 'ё', если помните, имеют в Unicode особое соотношение с русским алфавитом, а поэтому заслуживают особой проверки … как и 'Й' и 'й'.)
Код: Выделить всё
$ ./regex3 "^([^,]*),([^,]*),([^,]*)$"
123,4567,898709
'123,4567,898709' ->
0/15 : 123,4567,898709
0/3 : 123
4/8 : 4567
9/15 : 898709
a,b,c
'a,b,c' ->
0/5 : a,b,c
0/1 : a
2/3 : b
4/5 : c
й,ё,Ё
'й,ё,Ё' ->
0/8 : й,ё,Ё
0/2 : й
3/5 : ё
6/8 : Ё
слово,ещё слово,снова слово
'слово,ещё слово,снова слово' ->
0/50 : слово,ещё слово,снова слово
0/10 : слово
11/28 : ещё слово
29/50 : снова слово
слово , word, ещё слово
'слово , word, ещё слово' ->
0/36 : слово , word, ещё слово
0/11 : слово
12/17 : word
18/36 : ещё слово
^C