2016-07-19 2 views
0

Я хочу выделить знаки препинания и символы из основного текста, чтобы разделить их как отдельные токены. У меня есть текстовый файл, содержащий следующие символы %&()+,-./:;=–‘’“”″, и я хочу заменить каждый символ \ssymbol\s (\s означает пробел), и если два символа одного типа, например. .. происходят рядом друг с другом, я хочу их заменить \s..\s. Это то, что я пытался до сих пор:Замена подстроки пробелом + подстрока + пробел с использованием regex Python3.x

>>> punc = "[%&\(\)\+,-./:;=–‘’“”″]+" 
>>> import re 
>>> pattern = re.compile(punc) 
>>> text = "hi. hi.. hi; hi;; 55% good& good&&" 
>>> text = re.sub(pattern, ' '+str(pattern)+' ', text) 

Когда я печатаю текст, я получаю следующее:

>>> print(text) 
hi <_sre.SRE_Pattern object at 0x00000000035E14E0> hi <_sre.SRE_Pattern object at 0x00000000035E14E0> hi <_sre.SRE_Pattern object at 0x00000000035E14E0> hi <_sre.SRE_Pattern object at 0x00000000035E14E0> 55 <_sre.SRE_Pattern object at 0x00000000035E14E0> x <_sre.SRE_Pattern object at 0x00000000035E14E0> 

Но я хочу выход быть похожим на это:

hi . hi .. hi ; hi ;; 55 % good & good && 

После нескольких попыток я понял, что не могу скомпилировать правильное регулярное выражение. Ваша любезная помощь очень ценится!

ответ

1

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

Почему вы видели, что вы видели

В функции re.sub, когда вы даете ему ' '+str(pattern)+' ' в качестве третьего параметра, это получает оценку в строку " <_sre.SRE_Pattern object at some_memory_location> ", поскольку str(pattern) возвращает строковое представление объекта шаблона, а не модель.

Как в сторону, на Python 3.4 и 3.5, str(pattern) возвращает re.compile('[%&\\(\\)\\+,-./:;=–‘’“”″]') для меня, какую версию Python вы используете? Возможно, это версия Python 2?

Решение

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

>>> import re 
>>> pattern = re.compile(r"([%&\(\)\+,-./:;=–‘’“”″]+)") 

Обратите внимание на мой строковый литерал, я использовал r до начала строки. Это обозначает необработанную строку, которая заставляет строку игнорировать любую escape-последовательность , как определено Python. Например, escape-последовательность представляет собой, например, '\t', которая обозначает вкладку. Однако, если вы используете r'\t', то это фактическая строка \t.

>>> text = "hi. hi.. hi; hi;; 55% good& good&&" 
>>> pattern.sub(r' \1 ', text) 
'hi . hi .. hi ; hi ;; 55 % good & good && ' 

Примечание я просто использовал метод sub объекта шаблона, а не функции уровня модуля re.sub. Это неважно, но мне кажется, что это чище. Кроме того, для аргумента замены я использовал r' \1 '. Этот \1 относится к первой группе , снятой вашим шаблоном. Если у вас было более одной группы, вы могли бы использовать что-то вроде \2 \1, если вы хотите, например, отменить какой-либо шаблон. Это снова, это escape-последовательность!

Потенциальное улучшение

Было неясно, в спецификации, как вы хотели бы иметь дело с более чем 2 характера, например, три символа. Таким образом, ваша модель будет иметь дело с этой ситуацией Thusly:

>>> text2 = "hi. hi.. hi; hi;; 55% good& good&& hi &&& hello," 
>>> pattern.sub(r' \1 ', text2) 
'hi . hi .. hi ; hi ;; 55 % good & good && hi &&& hello , ' 

Возможно, это то, что вы что, но, может быть, вы хотите, чтобы рассмотреть «& & &» в виде двух отдельных матчей: «& &» и «&». Вы можете иметь дело с этой ситуацией с помощью кванторов:

>>> pattern2 = re.compile(r'([%&\(\)\+,-./:;=–‘’“”″]{1,2})') 
>>> pattern2.sub(r' \1 ', text2) 
'hi . hi .. hi ; hi ;; 55 % good & good && hi && & hello , ' 

Вместо того, чтобы использовать + знак, который обозначает один или более-, вы можете использовать кронштейн обозначения, чтобы иметь более точный контроль. Например, {1,3} будет соответствовать от 1 до 3. {3} будет соответствовать точно 3. {3,} будет соответствовать 3 или более.

+0

Большое вам спасибо за помощь. Я не думал, что это было так просто решить мою проблему, как вы адекватно объяснили. Что касается версии Python, я пытался ее реализовать на 3.3.2. Сейчас я установлю 3,4. Что касается раздела улучшения, я хотел иметь дело с одним или несколькими, даже тремя символами того же типа, которые должны рассматриваться как одно совпадение, и это то, что вы продемонстрировали. Еще раз спасибо за вашу помощь. – Mohammed

+0

Однако я хочу понять использование '.sub (r '\ l', ...)'. – Mohammed

+0

@Mohammed Ah! Да, это просто относится к первой группе, захваченной вашим шаблоном! Если у вас было несколько групп, вы могли бы ссылаться на третье как на нечто вроде 'Это третья группа: \ 3'. См. Мое редактирование. –

Смежные вопросы