Python正则表达式意外替换中文字符

2024-05-20 14:10:35 发布

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

我有一份中文字典词条列表(基于cc-cedict),包含以下格式的中文和拉丁字符,用换行符分隔:

(source.txt)

traditional_chars simplified_chars, pinyin, definition

山牆 山墙,shan1 qiang2,gable

B型超聲 B型超声, B xing2 chao1 sheng1,type-B ultrasound

我想在繁体字和简体字之间加一个逗号:

(Desired result)

山牆,山墙,shan1 qiang2,gable

B型超聲,B型超声, B xing2 chao1 sheng1,type-B ultrasound

regex101中进行了一些实验后,我想出了这样一个模式:

[A-z]*[\u4300-\u9fff]+(\s)[A-z]*[\u4300-\u9fff]+,

我尝试用以下代码在Python中应用此模式:

import re
sourcepath = 'sourcefile.txt'
destpath = 'result.txt'
pattern = '[A-z]*[\u4300-\u9fff]+(\s)[A-z]*[\u4300-\u9fff]+,'

source = open(sourcepath, 'r').read()
dest = open(destpath, 'w')
result = re.sub(pattern, ',', source)
dest.write(result)
dest.close()

但当我打开结果.txt,我得到的结果不是我预期的:

,shan1 qiang2,gable

, B xing2 chao1 sheng1,type-B ultrasound

我还尝试使用以下模式的regexp模块:

[A-z]*\p{Han}(\s)[A-z]*\p{Han}

但结果是一样的。在

我认为通过将\s字符放在括号中,它将构成一个捕获组,并且只替换该空格。但看起来汉字也在被取代。我是不是在正则表达式、代码或两者都出错了?我应该如何改变它以获得期望的结果?在


Tags: txtsourcetype模式resultdestultrasoundu9fff
3条回答

如果你有奇数个中文“单词”,你的模式应该考虑重叠匹配。使用lookaheads:

re.sub(r'(?i)[A-Z]*[\u4300-\u9fff]+(?=\s+[A-Z]*[\u4300-\u9fff]+)', r'\g<0>,', source)
                                   ^^^                         ^

或者使用一个原子组模拟,在一个正的前瞻中结合消费模式中的反向引用进行捕获,并进行前瞻性检查,看是否已经有逗号:

^{pr2}$

请参阅regex demo(和demo 2)-不要注意\x{}符号,因为我使用的是PHP选项,所以它只用于演示)。在

参见IDEONE Python 3 demo

import re
p = re.compile(r'[A-Z]*(?=([\u4300-\u9fff]+))\1(?!,)', re.IGNORECASE | re.U)
test_str = "山牆 山墙,shan1 qiang2,gable\nB型超聲 B型超声, B xing2 chao1 sheng1,type-B ultrasound"
result = p.sub(r"\g<0>,", test_str)
print(result)
# => 山牆, 山墙,shan1 qiang2,gable
# => B型超聲, B型超声, B xing2 chao1 sheng1,type-B ultrasound

I thought that by putting the \s character in parentheses, that it would make a capture group, and only that space would be replaced.

这不是捕获组的工作方式。所有匹配的内容仍然会被替换,但是对于捕获组,您可以引用替换中匹配的部分。在

我要改两行你的剧本:

pattern = '(?i)([a-z]*[\u4300-\u9fff]+)\s([a-z]*[\u4300-\u9fff]+)'

以及

^{pr2}$

使用示例代码在Python 3.5上测试:

result = re.sub(r"([\u4e00-\u9fff]+)\s+(?:[a-z]+)?([\u4e00-\u9fff]+)", r"\1,\2", subject, 0, re.IGNORECASE)

正则表达式解释

^{pr2}$

相关问题 更多 >