Вы видите поведение re
, которое очень «темное», почти на ошибке (или два).
# Python 2.7.1 & gt; & GT; & GT; import & gt; & gt; & gt; & gt; & gt; & gt; pat = r "b {1, 3} \ Z" & gt; & gt; & gt; bool (re.match (pat, "bb")) False & gt; & gt; & gt; & gt; & gt; bool (re.match (pat, "b {1, 3}")) True & gt; & gt; & gt; & gt; & gt; bool (re.match (pat, "bb", re.VERBOSE)) False & gt; & gt; & gt; & gt; & gt; bool (re.match (pat, "b {1, 3}", re.VERBOSE)) False & gt; & gt; & gt; & gt; & gt; & gt; bool (re.match (pat, "b {1,3}", re.VERBOSE)) True & gt; & gt; & gt; & gt; & gt; & gt;
Другими словами, шаблон "b {1, 3}"
соответствует буквальному тексту "b {1, 3}"
в нормальном режиме и буквальный текст "b {1,3}"
в режиме VERBOSE.
«Закон наименьшего удивления» предполагает либо (1) пространство перед 3
был проигнорирован, и он соответствовал "b"
, "bb"
или "bbb"
в случае необходимости [предпочтительнее] или (2) исключение во время компиляции.
Взгляд на него по-другому: две возможности: (a) Человек, который пишет Еще одна перспектива: когда пространство достигнуто, оно уже разобралось Обновить Сообщение об ошибке подано. «{1, 3}»
пронизана духом PEP8 и полагает, что он предписывающий и применяется повсюду. (б) Человек, который пишет, что протестировал re
недокументированное поведение и фактически хочет сопоставить литеральный текст "b {1, 3} "
и извратно хочет использовать r" b {1, 3} "
вместо явного экранирования: r" b \ {1, 3} "[ ! d14]. Мне кажется, что (а) гораздо вероятнее, чем (б), и
re
должны действовать соответственно. {
, строка цифр и запятая, т.е. хорошо в {m, n}
"оператор" ... молча игнорировать неожиданный символ и рассматривать его как бы это был буквальный текст ошеломляющий, perlish и т. д.
[^\P{P}-]+
\P
является дополнением к \p
, а не пунктуацией. Таким образом, это соответствует любому, что есть not (не пунктуация или тире), в результате чего все знаки препинания, кроме тире.
Пример: http://www.rubular.com / r / JsdNM3nFJ3
Если вы хотите не запутанный путь, альтернативой является \p{P}(?<!-)
: совместить все знаки пунктуации, а затем проверить, что это не тире (используя отрицательный lookbehind). Рабочий пример: http://www.rubular.com/r/5G62iSYTdk
Вот как это сделать с модулем re
, если вы должны придерживаться стандартных библиотек:
# works in python 2 and 3
import re
import string
remove = string.punctuation
remove = remove.replace("-", "") # don't remove hyphens
pattern = r"[{}]".format(remove) # create the pattern
txt = ")*^%{}[]thi's - is - @@#!a !%%!!%- test."
re.sub(pattern, "", txt)
# >>> 'this - is - a - test'
Если производительность имеет значение, вы можете использовать str.translate
, поскольку это быстрее, чем использование регулярного выражения . В Python 3 код txt.translate({ord(char): None for char in remove})
.
Вы можете либо указать пунктуацию, которую вы хотите удалить вручную, как в [._,]
или поставить функцию вместо строки замены:
re.sub(r"\p{P}", lambda m: "-" if m.group(0) == "-" else "", text)
[^\P{P}\-.]+
, а второй\p{P}(?<![\-.])
. Довольно просто. – Kobi 18 January 2014 в 22:13-
имеет пространственное значение в символьном классе, как в[a-z]
- это указывает диапазон. Мне обычно нравится избегать этого, чтобы избежать потенциальных ошибок. – Kobi 18 January 2014 в 22:17