Пунктуационная специальная последовательность \ p терпит неудачу в регулярном выражении [duplicate]

Вы видите поведение 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 и т. д.

Обновить Сообщение об ошибке подано.

18
задан John 18 January 2014 в 22:11
поделиться

3 ответа

[^\P{P}-]+

\P является дополнением к \p, а не пунктуацией. Таким образом, это соответствует любому, что есть not (не пунктуация или тире), в результате чего все знаки препинания, кроме тире.

Пример: http://www.rubular.com / r / JsdNM3nFJ3

Если вы хотите не запутанный путь, альтернативой является \p{P}(?<!-): совместить все знаки пунктуации, а затем проверить, что это не тире (используя отрицательный lookbehind). Рабочий пример: http://www.rubular.com/r/5G62iSYTdk

21
ответ дан Pale Blue Dot 16 August 2018 в 05:29
поделиться
  • 1
    Большое спасибо. Как насчет исключения нескольких? Такие как '.' также. – John 18 January 2014 в 22:09
  • 2
    @Anonymous - первым будет [^\P{P}\-.]+, а второй \p{P}(?<![\-.]). Довольно просто. – Kobi 18 January 2014 в 22:13
  • 3
    Почему нужно было «\» теперь после {P}, а не в первом? – John 18 January 2014 в 22:15
  • 4
    @Anonymous - Хороший вопрос! Это не строго необходимо - я обычно предпочитаю его включать. - имеет пространственное значение в символьном классе, как в [a-z] - это указывает диапазон. Мне обычно нравится избегать этого, чтобы избежать потенциальных ошибок. – Kobi 18 January 2014 в 22:17

Вот как это сделать с модулем 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}).

10
ответ дан Community 16 August 2018 в 05:29
поделиться

Вы можете либо указать пунктуацию, которую вы хотите удалить вручную, как в [._,] или поставить функцию вместо строки замены:

re.sub(r"\p{P}", lambda m: "-" if m.group(0) == "-" else "", text)
0
ответ дан Cu3PO42 16 August 2018 в 05:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: