2015-01-20 2 views
2

Я пытаюсь разобрать строки таким образом, чтобы выделить все компоненты слова, даже те, которые были сокращены. Например, токенизация «не должна» будет [«should», «not»].Python regex: tokenizing английские сокращения

NLTK модуль не кажется, с этой задачей, однако, как:

«Я wouldn't've сделал это.»

размечает как:

[ 'Я', "не будет", "'ве", 'сделано', 'что', "".]

где желаемый токенизация «wouldn't've» была: ['would', "not", "ve"]

После изучения общих английских сокращений я пытаюсь написать регулярное выражение для выполнения задания но мне сложно определить, как совместить «ve» только один раз. Например, следующие маркеры могут все прекратить сокращение:

нет, 'В.Э.,' d 'LL,' s, «м 'ре

Но маркер«' ве»может также следовать за другими сокращениями, такие как:

'd'ве, n't've и (предположительно)' ll've

на данный момент я пытаюсь пререкаться это регулярное выражение:

\ b [a-zA-Z] + (? :('d |' ll | not) ('ve)?) | (' S | 'm |' re | 've) \ Ъ

Тем не менее, эта модель также совпадает с плохо сформированы:

"wouldn't've've"

кажется, проблема заключается в том, что третий апостроф квалифицируется как границы слова, так что конечный токен «ve» соответствует всему регулярному выражению.

Я не мог придумать способ отличить границу слова от апострофа, и, в противном случае, я открыт для консультаций по альтернативным стратегиям.

Кроме того, мне любопытно, есть ли способ включить специальный символ границы слова в класс символов. Согласно документации Python, \ b в символьном классе соответствует обратному пространству, и, похоже, это не так.

EDIT:

Вот результат:

>>>pattern = re.compile(r"\b[a-zA-Z]+(?:('d|'ll|n't)('ve)?)|('s|'m|'re|'ve)\b") 
>>>matches = pattern.findall("She'll wish she hadn't've done that.") 
>>>print matches 
[("'ll", '', ''), ("n't", "'ve", ''), ('', '', "'ve")] 

Я не могу понять, третий матч. В частности, я просто понял, что если третий апостроф соответствовал ведущему \ b, то я не знаю, что бы соответствовало классу символов [a-zA-Z] +.

ответ

2
(?<!['"\w])(['"])?([a-zA-Z]+(?:('d|'ll|n't)('ve)?|('s|'m|'re|'ve)))(?(1)\1|(?!\1))(?!['"\w]) 

EDIT: \ 2 является совпадением, \ 3 является первой группой, \ 4 второй и третьей.

+0

Спасибо. Но это путается: «Она пожелает, чтобы она не сделала этого». и возвращает много посторонних групп в другое время. – Schemer

+0

Можете ли вы привести несколько примеров, чтобы мы знали, что тестировать? Я отредактировал свой код, чтобы он работал с некоторыми из моих примеров и ваших. Демо: https://regex101.com/r/iV4cX6/1 – AMDcze

+0

Ваш взгляд вперед/назад на утверждения указал мне на это: '\ b (? Schemer

1

Вы можете использовать следующие полные регулярные выражения:

import re 
patterns_list = [r'\s',r'(n\'t)',r'\'m',r'(\'ll)',r'(\'ve)',r'(\'s)',r'(\'re)',r'(\'d)'] 
pattern=re.compile('|'.join(patterns_list)) 
s="I wouldn't've done that." 

print [i for i in pattern.split(s) if i] 

результат:

['I', 'would', "n't", "'ve", 'done', 'that.'] 
+1

Спасибо. Но это также соответствует плохо сформированному «не было бы», которое я бы хотел проигнорировать. – Schemer

1

Вы можете использовать регулярное выражение для разметить текст:

(?:(?!.')\w)+|\w?'\w+|[^\s\w] 

Использование:

>>> re.findall(r"(?:(?!.')\w)+|\w?'\w+|[^\s\w]", "I wouldn't've done that.") 
['I', 'would', "n't", "'ve", 'done', 'that', '.'] 
+1

Спасибо. Но этот шаблон не исключает слабо сформированного «не было бы». – Schemer

1
>>> import nltk 
>>> nltk.word_tokenize("I wouldn't've done that.") 
['I', "wouldn't", "'ve", 'done', 'that', '.'] 

так:

>>> from itertools import chain 
>>> [nltk.word_tokenize(i) for i in nltk.word_tokenize("I wouldn't've done that.")] 
[['I'], ['would', "n't"], ["'ve"], ['done'], ['that'], ['.']] 
>>> list(chain(*[nltk.word_tokenize(i) for i in nltk.word_tokenize("I wouldn't've done that.")])) 
['I', 'would', "n't", "'ve", 'done', 'that', '.'] 
0

Вот простой один

text = ' ' + text.lower() + ' ' 
text = text.replace(" won't ", ' will not ').replace("n't ", ' not ') \ 
    .replace("'s ", ' is ').replace("'m ", ' am ') \ 
    .replace("'ll ", ' will ').replace("'d ", ' would ') \ 
    .replace("'re ", ' are ').replace("'ve ", ' have ')