Почему Python `re.split ()` не разделяется на совпадения нулевой длины? - PullRequest
16 голосов
/ 26 апреля 2010

Одна особенность (в противном случае довольно мощный) модуля re в Python заключается в том, что re.split() никогда не будет разбивать строку при совпадении нулевой длины , например, если я хочу разбить строка вдоль границ слова:

>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!")
['Split', 'along', 'words,', 'preserve', 'punctuation!']

вместо

['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']

Почему у него есть такое ограничение? Это по дизайну? Другие вкусы регулярного выражения ведут себя так?

Ответы [ 3 ]

22 голосов
/ 26 апреля 2010

Это дизайнерское решение, которое было принято и могло пойти в любую сторону. Тим Питерс сделал этот пост , чтобы объяснить:

Например, если вы разделите «abc» по шаблону x *, что вы ожидать? Шаблон соответствует (с длиной 0) в 4 местах, но держу пари, что большинство людей будут удивлены, получив

['', 'a', 'b', 'c', '']

назад вместо (как они получают)

['abc']

Некоторые другие с ним не согласны. Гвидо ван Россум не хочет, чтобы оно изменилось из-за проблем с обратной совместимостью. Он сказал :

Я в порядке, добавив флаг, чтобы включить это поведение.

Редактировать

Существует обходной путь , опубликованный Яном Бурги:

>>> s = "Split along words, preserve punctuation!"
>>> re.sub(r"\s+|\b", '\f', s).split('\f')
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']

Где '\f' можно заменить любым неиспользованным символом.

2 голосов
/ 27 июля 2016

Чтобы обойти эту проблему, вы можете использовать режим VERSION1 пакета regex , который заставляет split() также производить совпадения нулевой длины :

>>> import regex as re
>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!", flags=re.V1)
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']
0 голосов
/ 29 апреля 2010

По сути, split () - это две разные функции в одну. Если вы предоставляете параметр, он ведет себя совершенно иначе, чем при вызове без него.

Сначала кажется, что

s.split() == s.split(' \t\n')

но это не тот случай, как вы показали. Док говорит:

[...] Если sep не указан или отсутствует, любая строка пробела является разделителем и пустые строки удаляются из результата. [...]

Даже при добавлении параметра «remove_empty» он все равно будет вести себя странно, поскольку значение по умолчанию «remove_empty» зависит от присутствующего там параметра «sep».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...