提取仅包含字母数字的单词的正则表达式

5
我正在寻找一个正则表达式,用于提取仅包含字母数字字符的单词:
string = 'This is a $dollar sign !!'
matches = re.findall(regex, string)
matches = ['This', 'is', 'sign']

这可以通过对字符串进行分词,并使用以下正则表达式逐个评估每个标记来完成:
^[a-zA-Z0-9]+$

由于性能问题,我希望能够提取包含字母和数字的令牌,而不需要对整个字符串进行标记化处理。我找到的最接近的方法是:
regex = \b[a-zA-Z0-9]+\b

但它仍然提取包含字母数字字符的子字符串:

string = 'This is a $dollar sign !!'
matches = re.findall(regex, string)
matches = ['This', 'is', 'dollar', 'sign']

有没有一个正则表达式可以做到这一点?我尝试过不同的方式,但是无法得出解决方案。


1
提示:您不能使用 \b,因为在 $dollar 之间存在一个单词边界。 - kindall
3个回答

5

不要使用单词边界,而是使用向前和向后查找空格(或字符串的开头/结尾):

(?:^|(?<= ))[a-zA-Z0-9]+(?= |$)

https://regex101.com/r/TZ7q1c/1

请注意,“a”是一个独立的字母数字单词,因此也包含在内。

['This', 'is', 'a', 'sign']

为了避免缓慢的逐个字符前向跟踪,我考虑使用占有匹配,然后在后面跟随非空格时使用(*SKIP)(*FAIL),但这需要正则表达式模块,它比本地的re更慢,并且尽管步骤较少,但不提供任何速度改进\s*\K[a-zA-Z0-9]*+(?:\S+(*SKIP)(*FAIL))? - CertainPerformance
谢谢你的回答。这正是我所寻找的。那么,在这种情况下,我想使用本地re仍然值得吗?另外,你认为这比@hegash提供的解决方案还要快吗? - GRoutar

5

不需要使用正则表达式,Python内置了isalnum字符串方法。请看以下示例:

string = 'This is a $dollar sign !!'

matches = [word for word in string.split(' ') if word.isalnum()]

谢谢你提醒我,我不知道。另一方面,我正在寻找性能最佳的解决方案。我会进行测试,但我相信正则表达式比根据条件迭代字符串并拆分它要快。 - GRoutar

0

[感谢Khabz的评论,我误解了问题]

根据您的意图,您也可以选择“分割”而不是“匹配”。

 >>> matches = re.split(r'(?:\s*\S*[\$\!]+\S*\s*|\s+)', string)

 ['This', 'is', 'a', 'sign', '']

如果您需要删除前导或尾随的空字符串:

>>> matches = [x for x in re.split(r'(?:\s*\S*[\$\!]+\S*\s*|\s+)', a) if x ]
['This', 'is', 'a', 'sign']

CertainPerformance使用前后查找的方式进行响应是最紧凑的。当指定排除内容时,使用split有时会更有优势,即上面的正则表达式描述了需要排除的内容。然而,在这种情况下,指定包含字母数字,因此使用split()不是一个好主意。

我认为"findall"是等效的。尽管如此,您提供的解决方案不符合要求。"dollar"不应该匹配,因为该单词包含一个非字母数字字符("$dollar")。 - GRoutar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接