Несоответствие Python 2 и 3 're.sub'

Я пишу функцию для разделения чисел и некоторых других вещей из текста в python. Код выглядит примерно так:

EN_EXTRACT_REGEX = '([a-zA-Z]+)' NUM_EXTRACT_REGEX = '([0-9]+)' AGGR_REGEX = EN_EXTRACT_REGEX + '|' + NUM_EXTRACT_REGEX entry = re.sub(AGGR_REGEX, r' \1\2', entry) 

Теперь этот код отлично работает в python3, но он не работает под python2 и получает ошибку « непревзойденной группы ».

Проблема в том, что мне нужно поддерживать обе версии, и я не мог заставить ее работать правильно в python2, хотя я пробовал другие способы.

Мне любопытно, какой может быть корень этой проблемы, и есть ли какое-нибудь обходное решение?

One Solution collect form web for “Несоответствие Python 2 и 3 're.sub'”

Я думаю, что проблема может заключаться в том, что шаблон регулярного выражения совпадает с одним или другим подшаблоном EN_EXTRACT_REGEX и NUM_EXTRACT_REGEX , но не с обоими.

Когда re.sub() соответствует альфа-символам в первом шаблоне, он пытается заменить вторую ссылку на группу с помощью \2 которая терпит неудачу, потому что только первая группа соответствует – нет второй группы.

Точно так же, когда образец цифр сопоставляется, нет никакой группы \1 для замены, и поэтому это также терпит неудачу.

Вы можете видеть, что это имеет место с этим тестом в Python 2:

 >>> re.sub(AGGR_REGEX, r' \1', 'abcd') # reference first pattern abcd >>> re.sub(AGGR_REGEX, r' \2', 'abcd') # reference second pattern Traceback (most recent call last): .... sre_constants.error: unmatched group 

Разница должна заключаться в разных версиях движка regex для Python 2 и Python 3. К сожалению, я не могу дать окончательную причину разницы, однако в версии 3.5 для документа re.sub() документальное изменение относительно несравнимых групп :

Изменено в версии 3.5: Непревзойденные группы заменяются пустой строкой.

что объясняет, почему он работает в Python> = 3.5, но не в более ранних версиях: несогласованные группы в основном игнорируются.


В качестве обходного пути вы можете изменить свой шаблон, чтобы обрабатывать оба совпадения как одну группу:

 import re EN_EXTRACT_REGEX = '[a-zA-Z]+' NUM_EXTRACT_REGEX = '[0-9]+' AGGR_REGEX = '(' + EN_EXTRACT_REGEX + '|' + NUM_EXTRACT_REGEX + ')' # ([a-zA-Z]+|[0-9]+) for s in '', '1234', 'abcd', 'a1b2c3', 'aa__bb__1122cdef', '_**_': print(re.sub(AGGR_REGEX, r' \1', s)) 

Вывод


  1234
  ABCD
  a 1 b 2 c 3
  aa__ bb__ 1122 cdef
 _ ** _
  • Используйте Python для извлечения длин ветвей из Newick Format
  • Заменить одиночные кавычки двойным с исключением некоторых элементов
  • Выбор элементов в массиве numpy с использованием регулярных выражений
  • Юникодное регулярное выражение для соответствия символьному классу китайских символов
  • Как объединить несколько регулярных выражений в одну строку?
  • pypeg2 - может ли это выражение анализироваться с использованием грамматики привязки?
  • Существует ли Perl-эквивалент re.findall / re.finditer Python (результаты итеративного регулярного выражения)?
  • сопоставление нескольких строк в python
  • Удаление Unicode \ uxxxx в String из JSON с использованием Regex
  • Разделенная строка Python на основе регулярного выражения
  • Сравнение скорости несогласованного регулярного выражения
  • Python - лучший язык программирования в мире.