使用regex Python3.x替换子空间+子串+空间的子串

时间:2016-07-19 23:23:08

标签: regex python-3.x substitution

我想从主文本中分隔标点符号和符号,以便将它们拆分为单独的标记。我有一个包含以下符号%&()+,-./:;=–‘’“”″的文本文件,我想用\ssymbol\s替换每个符号(\s表示空格),如果两个符号相同,例如..彼此相邻,我想用\s..\s替换它们。这是我到目前为止所尝试的:

>>> 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 个答案:

答案 0 :(得分: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。这表示一个原始字符串,它使字符串忽略Python 定义的任何转义序列。转义序列类似于'\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之类的内容。这又是一个逃脱序列!

潜在的改进

您的规范中不清楚您希望如何处理超过2个字符,例如三个字。因此,您的模式将如此处理这种情况:

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

也许这就是你的意思,但也许你想要考虑'&amp;&amp;&amp;&amp;'两个截然不同的比赛:'&amp;&amp;'和'&amp;'。您可以使用量词来处理这种情况:

>>> 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或更多。