Python正则表达式用于匹配重复标点符号和符号
我需要一个正则表达式,可以匹配重复的标点符号和符号。也就是说,所有重复的非字母数字和非空格的字符,比如……、???、!!!、###、@@@、+++等等。必须是同一个字符重复,而不是像“!?@”这样的组合。
我试过 [^\s\w]+,虽然它能匹配到所有的!!!、???、$$$的情况,但它匹配的内容比我想要的还要多,因为它也会匹配“!?@”。
有人能帮我解答一下吗?谢谢。
4 个回答
编辑:@Firoze Lafeer 提出了一个答案,使用一个正则表达式就能完成所有操作。我会保留这个内容,以防有人对将正则表达式和过滤功能结合起来感兴趣,但对于这个问题,使用 Firoze Lafeer 的答案会更简单、更快。
在我看到 Firoze Lafeer 的答案之前写的回答如下,未做更改。
一个简单的正则表达式无法做到这一点。经典的总结是“正则表达式无法计数”。这里有讨论:
对于 Python 的解决方案,我建议将正则表达式和一些 Python 代码结合起来。正则表达式会过滤掉所有不是某种标点符号连续出现的内容,然后 Python 代码会检查并排除错误匹配(即虽然是标点符号的连续出现,但并不是同一种字符)。
import re
import string
# Character class to match punctuation. The dash ('-') is special
# in character classes, so put a backslash in front of it to make
# it just a literal dash.
_char_class_punct = "[" + re.escape(string.punctuation) + "]"
# Pattern: a punctuation character followed by one or more punctuation characters.
# Thus, a run of two or more punctuation characters.
_pat_punct_run = re.compile(_char_class_punct + _char_class_punct + '+')
def all_same(seq, basis_case=True):
itr = iter(seq)
try:
first = next(itr)
except StopIteration:
return basis_case
return all(x == first for x in itr)
def find_all_punct_runs(text):
return [s for s in _pat_punct_run.findall(text) if all_same(s, False)]
# alternate version of find_all_punct_runs() using re.finditer()
def find_all_punct_runs(text):
return (s for s in (m.group(0) for m in _pat_punct_run.finditer(text)) if all_same(s, False))
我写的 all_same()
函数是为了让它在迭代器和字符串上都能正常工作。Python 内置的 all()
对于空序列会返回 True
,但我们在这个特定情况下并不想要这样,所以我为期望的基础情况设置了一个参数,并将其默认值设为 True
,以匹配 all()
的行为。
这个方法尽可能多地利用了 Python 的内部机制(正则表达式引擎或 all()
),所以应该会比较快。对于较大的输入文本,你可能想要重写 find_all_punct_runs()
,使用 re.finditer()
而不是 re.findall()
。我给了一个例子。这个例子还返回了一个生成器表达式,而不是一个列表。你总是可以强制它生成一个列表:
lst = list(find_all_punct_runs(text))
我觉得你可能在寻找这样的东西:
[run for run, leadchar in re.findall(r'(([^\w\s])\2+)', yourstring)]
举个例子:
In : teststr = "4spaces then(*(@^#$&&&&(2((((99999****"
In : [run for run, leadchar in re.findall(r'(([^\w\s])\2+)',teststr)]
Out: ['&&&&', '((((', '****']
这个代码会给你一个列表,里面包含了连续的字符,但会把字符串中的4个空格和像'*(@^'这样的序列排除掉。
如果这不是你想要的结果,你可以修改一下你的问题,提供一个示例字符串,并明确你希望看到的输出是什么。
试试这个模式:
([.\?#@+,<>%~`!$^&\(\):;])\1+
\1
是指第一个匹配到的组,也就是括号里的内容。
你需要根据需要扩展标点符号和符号的列表。