LINUX.ORG.RU

pcre: поиск «целые слова» с utf-8 текстом


0

1

Прошу помощи зала. Дано: тестовый файл вида

'time'
Время
'Time'
'время'
\время=
"время+
:вреМя-
;время_
'время)
'время(
'время*
'время&
_время&
'время^
'1234время%
`время!
~время@
'eeeвремяeetimertet^

Надо доказать, что регексп \bвремя\b будет работать наравне с регекспом \btime\b... или надо найти замену \b (граница слова). Особенность: используется glib-pcre (можно и классический libpcre). для упрощения задачи скопируйте тестовые данные в файл. откройте в mcedit (серии 4.7.*). нажмите F7 и вбивайте регекспы.

P.S. Что самое интересное: \Bвремя\B работает как надо... а вот \Btime\B уже не срабатывает... в принципе, это объяснимо, если принять, что «In all flavors, the characters [a-zA-Z0-9_] are word characters» - а про остальные нац.символы разрабы pcre, наверное, не догадываются.. :(

http://midnight-commander.org/ticket/2396

P.P.S Регексп, выдранный из grep, находит немного неправильно. Нужно, чтобы находилось только «время», а с grep'овым регекспом находит «\время=» (то есть, с окружающими символами).

★★★★★

Последнее исправление: Slavaz (всего исправлений: 1)

$ perl -C63 -Mutf8 -ne 'print if /\bвремя\b/' test.txt
'время'
\время=
"время+
'время)
'время(
'время*
'время&
'время^
`время!
~время@

$ grep -w 'время' test.txt
'время'
\время=
"время+
'время)
'время(
'время*
'время&
'время^
`время!
~время@

$ grep -P '\bвремя\b' test.txt
'eeeвремяeetimertet^

$ pcregrep --utf-8 -w 'время' test.txt
'eeeвремяeetimertet^

т.е. с юникодными границами слов корректно умеют работать только сам перл и греп с родным алгоритмом. греп в режиме перл-выражений (pcre использует, наверное), как и сам pcre (собран с --enable-utf8) в этом деле не помощники. такие дела.

arsi ★★★★★
()
Ответ на: комментарий от Sorcerer

> Нужно вызывать pcre_compile() с флагом PCRE_UTF8.

К сожалению, не всегда применим этот флаг. особенно при поиске по koi8-r тексту, например :( Или при поиске по «всем известным кодировкам» - cp866, cp1251, ... (компилируется по регекспу на каждую кодировку). Glib-pcre по дефолту и компилится как utf-8, но для поиска по прочим кодировкам(одновременно) пришлось добавить RAW-флаг.

Slavaz ★★★★★
() автор топика
Ответ на: комментарий от arsi

> grep -w 'время' test.txt

в данном случае grep создаёт такой регексп:

(^|([^[:alnum:]_]))(время)([^[:alnum:]_]|$)

что для нужд грепа вполне достаточно, но в нашем случае есть подсветка найденного в строке и становится видно, что ищется не только само слово «время», но и окружающие это слово символы.

Можно ли как-то проэмулировать \b? Моей воображалки уже не хватает составить регексп :(

Slavaz ★★★★★
() автор топика
Ответ на: комментарий от Slavaz

так а в чём проблема-то? этот регексп возвратит три элемента:

\1 — один символ перед (если есть, иначе пустую строку);
\2 — собственно само искомое («время»);
\3 — символ после (если есть).

т.о. искомая строка будет будет начинаться с start+strlen(part(1)), её длина — part(2). с api pcre не работал, но подозреваю, что там можно получить начало и конец/длину произвольного сегмента без лишних расчётов…

arsi ★★★★★
()
Ответ на: комментарий от arsi

arsi, очевидное лежит, как всегда, на поверхности - и прятать-то не нужно, а фиг найдёшь :) Эффект «замыленного глаза».

Конечно же Вы правы: брать второй найденный токен и с ним работать (только немного потом изменить ещё код, чтобы брать этот второй токен)...

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

Спасибо!

Slavaz ★★★★★
() автор топика
Ответ на: комментарий от andreyu

> Это в MC пойдет? Для чего?
Да, в mc. Поиск по словам. Сейчас оно работает только для английских слов.

Slavaz ★★★★★
() автор топика
Ответ на: комментарий от andreyu

сейчас не работает поиск с галкой «Слово целиком», если поиск происходит не по ASCII, надуюсь слава добьёт в ближайшее время.

angel_il ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.