在Python中使用正则表达式捕获表情符号

8 投票
4 回答
8588 浏览
提问于 2025-04-17 13:59

我想要一个正则表达式,用来匹配表情符号,比如 ":)" 和 ":("。它还应该能够识别重复的表情,比如 ":) :)" 和 ":) :(",但要过滤掉无效的写法,比如 ":( ("。

我现在有一个正则表达式,但它却匹配到了 ":( ("。

bool( re.match("(:\()",str) ) 

我可能漏掉了一些明显的东西,希望能有人帮我解决这个看似简单的问题。

4 个回答

2

试试这个表达式 (?::|;|=)(?:-)?(?:\)|\(|D|P)。我没有做过很多测试,但看起来它能匹配到正确的内容,而不会多匹配其他的...

In [15]: import re

In [16]: s = "Just: to :)) =) test :(:-(( ():: :):) :(:( :P ;)!"

In [17]: re.findall(r'(?::|;|=)(?:-)?(?:\)|\(|D|P)',s)
Out[17]: [':)', '=)', ':(', ':-(', ':)', ':)', ':(', ':(', ':P', ';)']
3

也许可以这样做:

re.match('[:;][)(](?![)(])', str)
9

我想我终于明白你在问什么了。看看下面的内容:

import re

smiley_pattern = '^(:\(|:\))+$' # matches only the smileys ":)" and ":("

def test_match(s):
    print 'Value: %s; Result: %s' % (
        s,
        'Matches!' if re.match(smiley_pattern, s) else 'Doesn\'t match.'
    )

should_match = [
    ':)',   # Single smile
    ':(',   # Single frown
    ':):)', # Two smiles
    ':(:(', # Two frowns
    ':):(', # Mix of a smile and a frown
]
should_not_match = [
    '',         # Empty string
    ':(foo',    # Extraneous characters appended
    'foo:(',    # Extraneous characters prepended
    ':( :(',    # Space between frowns
    ':( (',     # Extraneous characters and space appended
    ':(('       # Extraneous duplicate of final character appended
]

print('The following should all match:')
for x in should_match: test_match(x);

print('')   # Newline for output clarity

print('The following should all not match:')
for x in should_not_match: test_match(x);

你原来的代码有问题,主要是你的正则表达式写错了:(:\()。我们来分析一下。

外面的括号是一个“分组”。如果你要替换字符串时会用到它们,它们可以让你一次性对一组字符应用正则表达式的操作。所以,你实际上是在说:

  • ( 开始一个分组
    • :\( ... 进行正则表达式操作 ...
  • ')' 结束这个分组

这里的:并不是正则表达式中的特殊字符,所以它只是一个冒号。而\是一个特殊字符,它的意思是“接下来的字符是字面意思,不是正则表达式的操作符”。这叫做“转义序列”。把你的正则表达式完全翻译成中文,就是:

  • ( 开始一个分组
    • : 一个冒号字符
    • \( 一个左括号字符
  • ) 结束这个分组

我用的正则表达式稍微复杂一点,但也不难。我们来分析一下:^(:\(|:\))+$

^$分别表示“行的开始”和“行的结束”。现在我们有了:

  • ^ 行的开始
    • (:\(|:\))+ ... 进行正则表达式操作 ...
  • $ 行的结束

... 所以它只匹配整行的内容,而不是字符串中间的部分。

我们知道()表示一个分组。+的意思是“一个或多个”。现在我们有:

  • ^ 行的开始
  • ( 开始一个分组
    • :\(|:\) ... 进行正则表达式操作 ...
  • ) 结束这个分组
  • + 匹配一个或多个这样的内容
  • $ 行的结束

最后,还有|(管道符)操作符。它的意思是“或者”。所以,结合我们之前学到的转义字符,我们可以完成翻译:

  • ^ 行的开始
  • ( 开始一个分组
    • : 一个冒号字符
    • \( 一个左括号字符
  • | 或者
    • : 一个冒号字符
    • \) 一个右括号字符
  • ) 结束这个分组
  • + 匹配一个或多个这样的内容
  • $ 行的结束

希望这对你有帮助。如果没有,请告诉我,我会很乐意修改我的回答。

撰写回答