python正则表达式:如何从一个字符串中删除所有标点字符,但将它们保留在数字之间?

2024-10-02 00:39:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在做一个中国NLP项目。我需要删除除数字之间的字符以外的所有标点字符,只保留中文字符(\u4e00-\u9fff)、字母数字字符(0-9a-zA-Z) 12-34中的连字符应保留,123后的等号应去掉。在

这是我的python脚本。在

import re
s = "中国,中,。》%国foo中¥国bar@中123=国%中国12-34中国"
res = re.sub(u'(?<=[^0-9])[^\u4e00-\u9fff0-9a-zA-Z]+(?=[^0-9])','',s)
print(res)

预期产出应该是

^{pr2}$

但结果是

中国中国foo中国bar中123=国中国12-34中国

我不明白为什么输出中有一个额外的等号?在


Tags: 项目importre脚本nlpfoo字母bar
2条回答

您的regex将首先检查"="与{}。这会成功的。然后它将检查lookbehind和lookahead,这两个操作都必须失败。Ie:如果其中一个成功了,这个角色就会保留下来。这意味着您的代码实际上保留了任何非字母数字、非中文的字符,这些字符在的任何边上。在

您可以尝试以下正则表达式:

u'([\u4e00-\u9fff0-9a-zA-Z]|(?<=[0-9])[^\u4e00-\u9fff0-9a-zA-Z]+(?=[0-9]))'

您可以这样使用它:

^{pr2}$

我建议在数字之间匹配并捕获这些字符(以便稍后在输出中恢复它们),并且只在其他上下文中匹配它们。在

在python2中,它看起来像

import re
s = u"中国,中,。》%国foo中¥国bar@中123=国%中国12-34中国"
pat_block = u'[^\u4e00-\u9fff0-9a-zA-Z]+';
pattern = u'([0-9]+{0}[0-9]+)|{0}'.format(pat_block)
res = re.sub(pattern, lambda x: x.group(1) if x.group(1) else u"" ,s)
print(res.encode("utf8")) # => 中国中国foo中国bar中123国中国12-34中国

参见Python demo

如果需要在任何Unicode数字中保留这些符号,则需要将[0-9]替换为\d,并将re.UNICODE标志传递给regex。在

正则表达式看起来像

^{pr2}$

它的工作原理如下:

  • ([0-9]+[^\u4e00-\u9fff0-9a-zA-Z]+[0-9]+)-第1组捕获
    • [0-9]+-1+位数
    • [^\u4e00-\u9fff0-9a-zA-Z]+-1+个字符,而不是在指定范围内定义的字符
    • [0-9]+-1+位数
  • |-或
  • [^\u4e00-\u9fff0-9a-zA-Z]+-1+个字符,而不是在指定范围内定义的字符

在python2.x中,当一个组在re.sub中不匹配时,对它的反向引用是None,这就是为什么需要lambda表达式来检查组1是否首先匹配。在

相关问题 更多 >

    热门问题