我有一个中文字典条目列表(基于 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()
但是当我打开 result.txt 时,得到的结果不是我所期望的:
,shan1 qiang2,gable
, B xing2 chao1 sheng1,type-B ultrasound
我还尝试使用具有这种模式的 regexp 模块:
[A-z]*\p{汉}(\s)[A-z]*\p{汉}
但结果是一样的。
我认为通过将\s 字符放在括号中,它会构成一个捕获组,并且只会替换那个空格。但看起来汉字也被替换了。我是否在正则表达式、代码或两者中犯了错误?我应该如何更改它以获得所需的结果?
请您参考如下方法:
如果您有奇数个中文“单词”,您的模式应该考虑重叠匹配。使用前瞻:
re.sub(r'(?i)[A-Z]*[\u4300-\u9fff]+(?=\s+[A-Z]*[\u4300-\u9fff]+)', r'\g<0>,', source)
^^^ ^
或者使用原子组仿真,在正先行中捕获并结合使用模式中的反向引用,并检查是否已经有逗号:
re.sub(r'(?i)[A-Z]*(?=([\u4300-\u9fff]+))\1(?!,)', r'\g<0>,', source)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
参见 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
