Regex для разделения слов в Python

Я разрабатывал регулярное выражение для split всех фактических слов из заданного текста:


Пример ввода:

"John mom went there, but he wasn't there. So she said: 'Where are you'"


Ожидаемый результат:

["John's", "mom", "went", "there", "but", "he", "wasn't", "there", "So", "she", "said", "Where", "are", "you"]



Я думал о регулярном выражении:

"(([^a-zA-Z]+')|('[^a-zA-Z]+))|([^a-zA-Z']+)"

После разбиения на Python результат содержит None элементы и пустые пробелы.

Как избавиться от элементов None? И почему пробелы не совпадали?


Редактировать:
Разделение на пробелы даст такие предметы, как: ["there."]
И расщепление на не-буквы, даст такие предметы, как: ["John","s"]
И расщепление на не-буквы, кроме ', даст такие элементы, как: ["'Where","you'"]

Ответы

Ответ 1

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

to_be_removed = ".,:!" # all characters to be removed
s = "John mom went there, but he wasn't there. So she said: 'Where are you!!'"

for c in to_be_removed:
    s = s.replace(c, '')
s.split()

НО, в вашем примере вы не хотите удалять апостроф в John's, но вы хотите удалить его в you!!'. Таким образом, строковые операции завершаются с ошибкой в ​​этой точке, и вам нужно точно отрегулированное регулярное выражение.

EDIT: возможно, простое регулярное выражение может решить вашу проблему:

(\w[\w']*)

Он будет захватывать все символы, начинающиеся с буквы и сохраняющие захват, в то время как следующий char является апострофом или буквой.

(\w[\w']*\w)

Это второе регулярное выражение для очень конкретной ситуации... Первое регулярное выражение может записывать слова типа you'. Это будет aviod это и только захват апострофа, если он находится внутри слова (не в начале или в конце). Но в этот момент возникает такая ситуация: вы не можете зафиксировать апостроф Moss' mom со вторым регулярным выражением. Вы должны решить, будете ли вы захватывать завершающий апостроф в именах, заканчивающихся wit s и определяющих право собственности.

Пример:

rgx = re.compile("([\w][\w']*\w)")
s = "John mom went there, but he wasn't there. So she said: 'Where are you!!'"
rgx.findall(s)

["John's", 'mom', 'went', 'there', 'but', 'he', "wasn't", 'there', 'So', 'she', 'said', 'Where', 'are', 'you']

ОБНОВЛЕНИЕ 2: Я нашел ошибку в своем регулярном выражении! Он не может записывать одиночные буквы, за которыми следует апостроф вроде A'. Исправлено новое регулярное выражение:

(\w[\w']*\w|\w)

rgx = re.compile("(\w[\w']*\w|\w)")
s = "John mom went there, but he wasn't there. So she said: 'Where are you!!' 'A a'"
rgx.findall(s)

["John's", 'mom', 'went', 'there', 'but', 'he', "wasn't", 'there', 'So', 'she', 'said', 'Where', 'are', 'you', 'A', 'a']

Ответ 2

У вас слишком много групп захвата в вашем регулярном выражении; сделать их не захватывающими:

(?:(?:[^a-zA-Z]+')|(?:'[^a-zA-Z]+))|(?:[^a-zA-Z']+)

Демо:

>>> import re
>>> s = "John mom went there, but he wasn't there. So she said: 'Where are you!!'"
>>> re.split("(?:(?:[^a-zA-Z]+')|(?:'[^a-zA-Z]+))|(?:[^a-zA-Z']+)", s)
["John's", 'mom', 'went', 'there', 'but', 'he', "wasn't", 'there', 'So', 'she', 'said', 'Where', 'are', 'you', '']

Это возвращает только один пустой элемент.

Ответ 3

Это регулярное выражение допускает только один завершающий апостроф, за которым может следовать еще один символ:

([\w][\w]*'?\w?)

Демо:

>>> import re
>>> s = "John mom went there, but he wasn't there. So she said: 'Where are you!!' 'A a'"
>>> re.compile("([\w][\w]*'?\w?)").findall(s)
["John's", 'mom', 'went', 'there', 'but', 'he', "wasn't", 'there', 'So', 'she', 'said', 'Where', 'are', 'you', 'A', "a'"]