正则表达式匹配'lol'到'lolllll'和'omg'到'omggg'等

4 投票
2 回答
3553 浏览
提问于 2025-04-16 05:14

大家好,我很喜欢正则表达式,但我真的不太会用。

我有一份大约400个缩写词的列表,比如lol、omg、lmao等等。每当有人输入这些缩写词时,它们会被替换成对应的英文意思(比如[laughter],或者类似的意思)。不过,人们总是喜欢把这些缩写的最后一个字母重复好几遍。

举个例子: omg 变成了 omgggg,lol 变成了 lollll,haha 变成了 hahahaha,lol 变成了 lololol。

我在想有没有人能给我一个正则表达式(最好是Python的)来处理这个问题?

谢谢大家。

(这是一个与Twitter相关的项目,用于主题识别。如果有人发推说“让我们去打篮球”,你怎么知道这条推文是关于篮球的等等。)

2 个回答

4

怎么样呢

\b(?=lol)\S*(\S+)(?<=\blol)\1*\b

(把lol换成omghaha等等)

这个规则会匹配lollololollolllllollollol等等,但不会匹配lololollllololly等等。

规则:

  1. 完全匹配单词lol
  2. 然后允许在单词的末尾重复一个或多个字符(比如lollol)。

所以\b(?=zomg)\S*(\S+)(?<=\bzomg)\1*\b会匹配zomgzomgggzomgmgmgzomgomgomg等等。

在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*

7

第一种方法 -

好吧,使用正则表达式你可以这样做 -

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 的值都很好用。

撰写回答