使用正则表达式 python 删除特殊字符时保留 smileys/emoticons

keeping smileys/emoticons while removing special characters using regex python

我正在使用以下代码来清理我的文本

def clean_str(s):
"""Clean sentence"""
  s = re.sub(r"[^A-Za-z0-9(),!?\'\`]", " ", s)
  s = re.sub(r"\'s", " \'s", s)
  s = re.sub(r"\'ve", " \'ve", s)
  s = re.sub(r"n\'t", " n\'t", s)
  s = re.sub(r"\'re", " \'re", s)
  s = re.sub(r"\'d", " \'d", s)
  s = re.sub(r"\'ll", " \'ll", s)
  s = re.sub(r",", " , ", s)
  s = re.sub(r"!", " ! ", s)
  s = re.sub(r"\(", " ", s)
  s = re.sub(r"\)", " ", s)
  s = re.sub(r"\?", " ? ", s)
  s = re.sub(r"\s{2,}", " ", s)
  s = re.sub(r'\S*(x{2,}|X{2,})\S*',"xxx", s)
  s = re.sub(r'[^\x00-\x7F]+', "", s)
  return s.strip()

如您所见,我正在删除括号和其他特殊字符。现在,我想在我的文本中完整保留以下模式,而不是删除它们

:), :-), :( 和 :-(

谁能帮我解决这个问题?

谢谢,

您应该问问自己,哪些模式与您想要 "protect" 的表情符号中的任何字符相匹配。您可以很容易地看到 r"[^A-Za-z0-9(),!?'`]", r"\(" and r"\)" 匹配这些字符。

因此,您可以修复这些模式:

s = re.sub(r":-?[()]|([^A-Za-z0-9(),!?'`])", lambda x: " " if x.group(1) else x.group(), s) # Match smilies and match and capture what you need to replace
s = re.sub(r"(?<!:)(?<!:-)\(", " ", s) # Prepend (?<!:)(?<!:-) lookbehinds
s = re.sub(r"(?<!:)(?<!:-)\)", " ", s) # Prepend (?<!:)(?<!:-) lookbehinds

:-?[()]|([^A-Za-z0-9(),!?'`]) 模式匹配笑脸以保护(:-?[()] 匹配 :,然后是可选的 -,然后是 ()) 或匹配并捕获非否定字符 class 中定义的任何字符并将其捕获到组 1 中。 lambda x: " " if x.group(1) else x.group() lambda 表达式根据组匹配实现自定义替换逻辑:如果第 1 组匹配,则进行替换,否则,笑脸将放回原处。

(?<!:)(?<!:-) 负后视确保 () 不匹配,如果它们以 ::- 为前缀。

注意 r'\S*(x{2,}|X{2,})\S*' 也可以匹配贴在 xxXX 上的表情符号。但是,修复这个问题很棘手,因为 :( 之类的表情符号如果不在非空白块的开头,可能会与 \S* 匹配,因此,您可以使用

s = re.sub(r'(:-[()])|(?:(?!:-?[()])\S)*(?:x{2,}|X{2,})(?:(?!:-?[()])\S)*',"xxx" if x.group(1) else x.group(), s)

策略类似于r":-?[()]|([^A-Za-z0-9(),!?'`])"模式,我们匹配并捕获笑脸,但是我们只允许匹配不以笑脸子字符串开头的非空白字符(\S)( (?:(?!:-?[()])\S)*).