正则表达式匹配'lol'到'lolllll'和'omg'到'omggg'等
大家好,我很喜欢正则表达式,但我真的不太会用。
我有一份大约400个缩写词的列表,比如lol、omg、lmao等等。每当有人输入这些缩写词时,它们会被替换成对应的英文意思(比如[laughter],或者类似的意思)。不过,人们总是喜欢把这些缩写的最后一个字母重复好几遍。
举个例子: omg 变成了 omgggg,lol 变成了 lollll,haha 变成了 hahahaha,lol 变成了 lololol。
我在想有没有人能给我一个正则表达式(最好是Python的)来处理这个问题?
谢谢大家。
(这是一个与Twitter相关的项目,用于主题识别。如果有人发推说“让我们去打篮球”,你怎么知道这条推文是关于篮球的等等。)
2 个回答
怎么样呢
\b(?=lol)\S*(\S+)(?<=\blol)\1*\b
(把lol
换成omg
、haha
等等)
这个规则会匹配lol
、lololol
、lollll
、lollollol
等等,但不会匹配lolo
、lollllo
、lolly
等等。
规则:
- 完全匹配单词
lol
。 - 然后允许在单词的末尾重复一个或多个字符(比如
l
、ol
或lol
)。
所以\b(?=zomg)\S*(\S+)(?<=\bzomg)\1*\b
会匹配zomg
、zomggg
、zomgmgmg
、zomgomgomg
等等。
在Python中,带注释:
result = re.sub(
r"""(?ix)\b # assert position at a word boundary
(?=lol) # assert that "lol" can be matched here
\S* # match any number of characters except whitespace
(\S+) # match at least one character (to be repeated later)
(?<=\blol) # until we have reached exactly the position after the 1st "lol"
\1* # then repeat the preceding character(s) any number of times
\b # and ensure that we end up at another word boundary""",
"lol", subject)
这也会匹配“原版”的版本(也就是lol
没有任何重复)。如果你不想要这个,可以用\1+
代替\1*
。
第一种方法 -
好吧,使用正则表达式你可以这样做 -
import re
re.sub('g+', 'g', 'omgggg')
re.sub('l+', 'l', 'lollll')
等等。
我想指出的是,使用正则表达式处理这个问题是一种非常脆弱和基础的方法。用户输入的字符串很容易就会让上面的正则表达式失效。我想说的是,这种方法需要大量的维护工作,你得观察用户常犯的错误模式,然后为这些情况创建特定的正则表达式。
第二种方法 -
你有没有考虑过使用 difflib
模块?这是一个可以帮助计算对象之间差异的模块。对你来说,特别重要的是 SequenceMatcher
。简单来说,来自官方文档的描述是 -
SequenceMatcher 是一个灵活的类,用于比较任何类型的序列,只要序列的元素是可哈希的。SequenceMatcher 尝试计算两个序列之间的“人性化差异”。其基本概念是寻找最长的 连续 且没有垃圾的匹配子序列。
import difflib as dl
x = dl.SequenceMatcher(lambda x : x == ' ', "omg", "omgggg")
y = dl.SequenceMatcher(lambda x : x == ' ', "omgggg","omg")
avg = (x.ratio()+y.ratio())/2.0
if avg>= 0.6:
print 'Match!'
else:
print 'Sorry!'
根据文档,任何大于 0.6 的比率都算是接近匹配。你可能需要根据你的数据需求来调整这个比率。如果你需要更严格的匹配,我发现任何大于 0.8 的值都很好用。