LINUX.ORG.RU

[regexp] простая задачка

 


0

0

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

Я сделал вот такое (python):

re.split("([\.,:;!\?]?\s)", S)

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

Да, в конце строки может не оказаться EOL (напр. конец файла).

★★

Да, забыл сказать - знаки препинания нужны только те, что указаны.

frpaul ★★
() автор топика

если правильно понял, как-то так:

pat = re.compile(r'[\.,:;!\?\n]|[^\.,:;!\?\n]+', re.M | re.S | re.U)
tokens = pat.findall(text)
только это, питона не знаю, хз что я там написал, но вроде работает :)

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

У меня должен получиться список типа ['слово', 'пробел', 'слово', 'запятая пробел'].

Сомневаюсь, что whitespace символы вообще нужно сохранять, кроме EOL. Но проблема именно в последнем. EOL нужно записать - из-за него же появляются лишние элементы в конце списка (строка оканчивается на EOL).

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

> 'запятая пробел'

тогда примерно так:

\r?\n|\r|[,:;!\?]?\.*\s|[^\.,:;!\?\s]+

> EOL нужно записать - из-за него же появляются лишние элементы в конце списка (строка оканчивается на EOL).

не распарсил…

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

> EOL нужно записать - из-за него же появляются лишние элементы в >конце списка (строка оканчивается на EOL).

Nevermind. Суть в том, что мой регексп работает нормально, пока в конце строки, которую я пытаюсь парсить, не поставишь EOL. Тогда в списке появляются лишние элементы (eol'ы). Не пойму откуда берутся.

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

попробовал так:
[,:;!\?]?\.*\s|[^\.,:;!\?\s]+
(отрезал начало с переводами каретки).

пропали лишние EOL в полученном списке.

Пытаюсь понять, как работает регексп:
Группа (после или (|) - понятно: ловим чистое слово без указанных знаков препинания и white space.
А с первой частью я что-то не разберусь.

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

>юзай re.compile - оно в 2 раза быстрее

Да, спасибо, уже заюзал. Просто пока в стадии отладки регекспа - это некритично.

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

> А с первой частью я что-то не разберусь.

[,:;!\?]?\.*\s


хм… не, лучше так: «[,:;!\?]*\.*\s», а то варианты «!!!», «!?..» и т.п. отлавливать не будет, только «...», «!..», «?..», … :(
а если русаб парсить, то тогда вообще «[\.,:;!\?]*\s» для всяких там «....?», «...!...!!...» и т.п. ;)

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

Я догадался и выпилил \.* - в этих текстах таких сочетаний нету. Ну разве что многоточие. Хм... :) Тогда \.{1, 3} что ли?

В общем проблему я вычислил.
Строки почему-то оканчиваются _пробелом_ и eol.
Плюс к тому - \r и \n распознаются по-отдельности, а надо - заодно «\r\n».

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

Еще раз поясню: «слово» один элемент, все что после «слова» (означенные знаки препинания и whitespace'ы) - другой элемент. Когда то, что идет после слова - сегментируется на более мелкие детали, то нарушается чередование слов и служебных символов в итоговом списке.

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

> Тогда \.{1, 3} что ли?

тогда лучше либо «(?:\.{3}|[\.,:;!\?])?\s», либо «(?:\.\.{2}?|[,:;!\?])?\s», ИМХО.

Плюс к тому - \r и \n распознаются по-отдельности, а надо - заодно «\r\n».

ну я же писал с самого начала: «\r?\n|\r|…», и будут распознаваться «\r\n», «\n» и «\r» как одна лексема.

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

> «слово» один элемент, все что после «слова» (означенные знаки препинания и whitespace'ы) - другой элемент.

pat = re.compile(r'[\.,:;!\?\s]+|[^\.,:;!\?\s]+', re.M | re.S | re.U)
tokens = pat.findall(text)

;)

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

>тогда лучше либо «(?:\.{3}|[\.,:;!\?])?\s», либо «(?:\.\.{2}?|[,:;!\?])?\s», ИМХО.

Вы молодец, оно работает.

Осталось сделать так, чтобы знак препинания + пробел + EOL воспринималось парсером как одна группа. Я не сообразил пока.
Можно вначале тупо отрезать EOL rstrip'ом, а потом отдельно приклеивать к последнему элементу списка. Но это, конечно, не «тру»...



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

> И, кстати, в группе [] ескейпить разве надо?

надо, но не всё ;) «[», «?», «*» и т.п. можно не эскейпить, но привычка же :)

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

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

«+» после «\s» :)

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

Не надо!

С меня пиво :)


Не надо, он коту все равно отдаст!

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