使用正则表达式 Python3.x 将子字符串替换为 space+substring+space

Replacing substring with space+substring+space using regex Python3.x

我想将标点符号和符号与正文分开,以便将它们拆分为单独的标记。我有一个包含以下符号 %&()+,-./:;=–‘’“”″ 的文本文件,我想用 \ssymbol\s 替换每个符号(\s 表示 space),如果两个相同的符号输入例如..彼此相邻,我想用\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 &&

经过几次尝试,我意识到我无法编译正确的正则表达式。非常感谢您的帮助!

处理您尝试做的事情的正确方法是使用捕获组。这会让你回顾你的比赛。首先,让我先解释一下为什么您的尝试会得到您所看到的输出。

为什么你看到了你所看到的

re.sub函数中,当你给它' '+str(pattern)+' '作为第三个参数时,它被评估为字符串" <_sre.SRE_Pattern object at some_memory_location> ",因为str(pattern)returns 模式对象的字符串表示,而不是模式的字符串表示。

顺便说一句,对于 Python 3.4 和 3.5,str(pattern) returns 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'  ', text)
'hi .  hi ..  hi ;  hi ;;  55 %  good &  good && '

注意我只是使用了模式对象的 sub 方法而不是模块级函数 re.sub。这没什么大不了的,但对我来说似乎更干净。另外,对于替换参数,我使用了 r' '。此 </code> 指的是您的模式捕获的 <em> 第一组 </em>。例如,如果你有多个组,你可以使用 <code> 之类的东西来反转某些模式。这又是一个转义序列!

潜在的改进

在您的规范中不清楚您希望如何处理超过 2 个字符,例如三个字符。所以你的模式会这样处理这种情况:

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

也许这就是您的意思,但也许您想将“&&&”视为两个不同的匹配项:“&&”和“&”。您可以使用量词来处理这种情况:

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

除了使用表示一个或多个的 + 符号,您还可以使用括号符号来进行更细粒度的控制。例如,{1,3} 将匹配 1 到 3。{3} 将恰好匹配 3。{3,} 将匹配 3 或更多。