regex findall предложение, исключая \ n - PullRequest
0 голосов
/ 27 января 2020

Короткий вопрос: Предположим, у меня есть такой текст:

sent one. sent two.
sent three
sent four

Я хочу получить предложения с таким результатом:

['sent one.', 'sent two.', 'sent three', 'sent four']

Длинный вопрос : Я хочу создать в python функцию, которая позволит вам делить текст на предложения (но я не хочу использовать токенизатор, импортированный из другого модуля). Как и в предыдущем примере, в дополнение к новой строке может быть несколько разделителей, которые могут вызвать начало нового предложения. Кроме того, я могу захотеть оставить эти разделители в предложении или нет. Так как требование может изменяться динамически, я хотел бы написать параметризованную функцию, которая позволит вам решить:

  1. , которые являются разделителями, которые разбивают предложение (например, \ n.!?:;)
  2. какие из них должны быть удалены (например, \ n)
  3. , при наличии каких символов разделитель действует (например, \ s, в некоторых случаях разделитель не должен работать)

Я не хотел задавать такой сложный вопрос, потому что на самом деле я уже написал код, который работал частично, но некоторые вещи не работают, и я боюсь, что это из-за перевода строки. Я показываю вам упрощенную версию кода, регулярное выражение внутри него генерируется динамически, я показываю вам только полученное сгенерированное регулярное выражение с параметрами по умолчанию, пропускающими код для генерации, который теперь бесполезен для вопроса:

def tokeniz_text(text, separator=['.', '!', '?'], to_remove=['\n'], bordering=['\s']):
    ...regex generation...
    re_divide = r"""(.+?{}{}){}{}""".format(pre, sep, nxt, rem)
    ...generated regex...
    (.+?(?:(?<!\.)|(?<!!)|(?<!\?))(?:\.|!|\?))(?:\.|!|\?|\s)|(?:(?:\s*)(?:\n+)(?:\s*))

причина, по которой я выбрал findall, и почему это казалось единственным методом RE, который мог бы позволить мне решить, сохранять ли разделители в отличие от split (что, однако, из того, что говорит Том, возможно, мне придется пересмотреть. Мне кажется, что это только два метода, которые возвращают список вхождений из всей проанализированной строки, поэтому я не рассматриваю остальные). Кроме того, я хотел использовать флаг точки, потому что, как вы можете видеть, я использую точку для захвата символов, и я подумал, что если точка автоматически не захватывает пробелы, я бы никогда не решил захватить их.

В любом случае Надеюсь, что сейчас ситуация не обратная и что вопрос слишком сложный! Извините, если я объяснил это неправильно, вчера я был очень сонным, и мне трудно понять, что объяснить, потому что мне это тоже не очень понятно, я попробую еще раз (даже если ответ Тима Бигелайзена будет правильным).

Ответы [ 2 ]

1 голос
/ 27 января 2020

Вот одна попытка начать работу:

>>> s = '''\
sent one. sent two.
sent three
sent four'''

>>> import re
>>> re.split(r'[.\n]\s*', s)
['sent one', 'sent two', 'sent three', 'sent four']

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

0 голосов
/ 27 января 2020

Мы можем попытаться использовать re.split на следующем шаблоне:

(?<=\.)\s+|\r?\n

Это разделит на точку, за которым следует любое количество пробелов, или на символе CR? LF. Обратите внимание, что в этом подходе сохраняются точки, оканчивающие предложение, так как они появляются в шаблоне только как фиксированная задняя ширина.

inp = """sent one. sent two.
sent three
sent four"""

matches = re.split(r'(?<=\.)\s+|\r?\n', inp)
print(matches)

Это печатает:

['sent one.', 'sent two.', 'sent three', 'sent four']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...