Почему Python `re.split()` разделяется на нулевую длину?
Одна особенность (в противном случае довольно мощного) модуля re
в Python заключается в том, что re.split()
никогда не разделит строку на нулевую длину, например, если я хочу разбить строку по границам слов:
>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!")
['Split', 'along', 'words,', 'preserve', 'punctuation!']
вместо
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']
Почему это ограничение? Это по дизайну? Существуют ли другие приемы регулярных выражений?
Ответы
Ответ 1
Это дизайнерское решение, которое было сделано и могло пойти в любом случае. Тим Петерс сделал этот пост, чтобы объяснить:
Например, если вы разделите "abc" по шаблону x *, что вы делаете ожидать? Шаблон соответствует (с длиной 0) в 4 местах, но я уверен, что большинство людей были бы удивлены, увидев
['', 'a', 'b', 'c', '']
назад вместо (как они это делают)
['abc']
Тем не менее некоторые другие не согласны с ним. Guido van Rossum не хочет, чтобы он менялся из-за проблем с обратной совместимостью. Он сделал сказать:
Я согласен с добавлением флага, чтобы включить это поведение.
Edit
Существует обходной путь, размещенный Ян Бурджи:
>>> s = "Split along words, preserve punctuation!"
>>> re.sub(r"\s+|\b", '\f', s).split('\f')
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']
Где '\f'
можно заменить любым неиспользуемым символом.
Ответ 2
Чтобы обойти эту проблему, вы можете использовать режим VERSION1
regex
package, который делает split()
производить нулевую длину также:
>>> import regex as re
>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!", flags=re.V1)
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']
Ответ 3
В принципе, split() - это две разные функции в одну. Если вы предоставляете параметр, он ведет себя совсем по-другому, чем при вызове без него.
Сначала кажется, что
s.split() == s.split(' \t\n')
но это не так, как вы показали.
Док говорит:
[...]
Если sep не указан или None, любая строка пробелов
является разделителем, и пустые строки удаляются из результата.
[...]
Даже добавив параметр "remove_empty", он все равно будет вести себя странно, потому что значение по умолчанию "remove_empty" зависит от параметра "sep".