删除中文字符的所有空格,同时在 Python 正则表达式中保留必要的英文空格

Remove all spaces for chinese characters while keeping necessary spaces for english in Python regex

假设我的数据框有一列混合了英文和中文的单词或字符,如果它们是中文单词,我想删除它们之间的所有白色space,否则如果它们是英语,然后只在单词之间保留一个 space:

我找到了从

中删除英文之间多余 space 的解决方案
import re
import pandas as pd

s = pd.Series(['V e  r y calm', 'Keen and a n a l y t i c a l',
'R a s h and careless', 'Always joyful', '你 好', '黑 石  公 司', 'FAN     STUD1O', 'beauty face 店  铺'])

代码:

regex = re.compile('(?<![a-zA-Z]{2})(?<=[a-zA-Z]{1}) +(?=[a-zA-Z] |.$)')
s.str.replace(regex, '')

输出:

Out[87]: 
0              Very calm
1    Keen and analytical
2      Rash and careless
3          Always joyful
4                    你 好
5               黑 石  公 司
dtype: object

但是正如你所见,它适用于英文,但没有删除中文之间的spaces,如何得到如下预期结果:

Out[87]: 
0              Very calm
1    Keen and analytical
2      Rash and careless
3          Always joyful
4                    你好
5                 黑石公司
dtype: object

参考:

您可以使用中文(嗯,CJK)Unicode property \p{script=Han}\p{Han}
但是,这仅在正则表达式引擎支持 UTS#18 Unicode 正则表达式时有效。默认 Python re 模块没有,但您可以使用替代方法(改进很多)regex engine:

import regex as re

rex = r"(?<![a-zA-Z]{2})(?<=[a-zA-Z]{1})[ ]+(?=[a-zA-Z] |.$)|(?<=\p{Han}) +"
test_str = ("V e  r y calm\n"
    "Keen and a n a l y t i c a l\n"
    "R a s h and careless\n"
    "Always joyful\n"
    "你 好\n"
    "黑 石  公 司")
result = re.sub(rex, "", test_str, 0, re.MULTILINE | re.UNICODE)

结果

Very calm
Keen and analytical
Rash and careless
Always joyful
你好
黑石公司

Online Demo(该演示使用 PCRE 仅用于演示目的)

在环视中使用单词边界 \b

(?<=\b\w\b) +(?=\b\w\b)

这匹配单个(以单词边界为界)“单词字符”之间的空格,其中包括汉字。

Pre python 3(例如java),\w只匹配英文字母,所以你需要添加unicode 标志 (?u) 到正则表达式的前面。


s = ['V e  r y calm', 'Keen and a n a l y t i c a l',
'R a s h and careless', 'Always joyful', '你 好', '黑 石  公 司']
regex = r'(?<=\b\w\b) +(?=\b\w\b)'
res = [re.sub(regex, '', line) for line in s]
print(res)

输出:

['Very calm', 'Keen and analytical', 'Rash and careless', 'Always joyful', '你好', '黑石公司']

这个正则表达式应该可以满足您的需求。请参阅底部的完整代码片段。

regex = re.compile(
    "((?<![a-zA-Z]{2})(?<=[a-zA-Z]{1})\s+(?=[a-zA-Z]\s|.$)|(?<=[\u4e00-\u9fff]{1})\s+)",
    re.UNICODE,
)

我对上面的正则表达式进行了以下修改: 现在,正则表达式基本上匹配出现在一个单字母单词之后和另一个单字符单词之前的所有空格。

  1. 我在正则表达式的末尾添加了一个部分 select 一个汉字后的所有空格(我使用了 unicode 范围 [\u4e00-\u9fff] 这也将涵盖日语和韩语。
  2. 我将正则表达式中的空格更改为空白字符 class \s 这样我们就可以捕获制表符等其他输入。
  3. 我还添加了 re.UNICODE 标志,这样 \s 也可以覆盖 unicode 空间。
import re
import pandas as pd

s = pd.Series(
    [
        "V e  r y calm",
        "Keen and a n a l y t i c a l",
        "R a s h and careless",
        "Always joyful",
        "你 好",
        "黑 石  公 司",
    ]
)

regex = re.compile(
    "((?<![a-zA-Z]{2})(?<=[a-zA-Z]{1})\s+(?=[a-zA-Z]\s|.$)|(?<=[\u4e00-\u9fff]{1})\s+)",
    re.UNICODE,
)
s.str.replace(regex, "")

输出:

0              Very calm
1    Keen and analytical
2      Rash and careless
3          Always joyful
4                     你好
5                   黑石公司
dtype: object