使用命令去除重音字符时如何保留中文字符?
这个问题我之前也碰到过!iconv转ASCII的思路其实走进死胡同了——因为中文根本不属于ASCII字符集,不管你加TRANSLIT还是IGNORE,它都没法被转成ASCII字符,只能变成问号。要实现「只去掉拉丁字符的重音,同时完整保留中文」,得换个思路:只针对带重音的拉丁字符做处理,中文完全不动。
推荐方案:用Perl快速处理
Perl对Unicode字符的分类处理很擅长,我们可以直接移除所有Unicode里的「非间距标记」(也就是那些附着在基础字符上的重音符号),而中文这类没有重音标记的字符会原封不动保留。
执行这个命令就行:
perl -CSDA -pe 's/\p{NonspacingMark}//g' test.bin > converted.bin
解释一下关键参数:
-CSDA:让Perl默认用UTF-8处理输入、输出,同时命令行参数也按UTF-8解析,确保中文不会乱码-pe:逐行读取输入文件,执行替换操作后实时输出s/\p{NonspacingMark}//g:全局替换掉所有Unicode非间距标记(比如É上面的重音符),基础字符(E)会保留,这样CAFÉ就变成了CAFE
备选方案:用Python精准处理(适合熟悉Python的用户)
如果你的环境里没有Perl,也可以用Python的Unicode归一化功能来实现:
python3 -c "import sys, unicodedata; print(''.join(c for c in unicodedata.normalize('NFKD', sys.stdin.read()) if not unicodedata.combining(c)), end='')" < test.bin > converted.bin
这个命令的逻辑是:
- 把输入文本用
NFKD模式归一化——这个模式会把带重音的字符分解成「基础字符+重音标记」(比如É → E + 重音符) - 遍历每个字符,只保留那些不是组合型重音标记的字符
- 最后输出处理后的文本,中文因为不会被分解出重音标记,所以完全保留
为什么原来的iconv命令不行?
再回头说下你原来的命令:iconv -f utf-8 -t ascii//TRANSLIT//IGNORE -o converted.bin test.bin
ascii//TRANSLIT只能处理拉丁系的字符,它能把É转成E,但中文不在它的处理范围内- 当遇到中文这类无法转成ASCII的字符时,
//IGNORE会直接把它们替换成问号(或者丢弃,取决于终端编码),所以才会出现一堆?????
你可以先拿小文件测试下效果,应该能完美满足需求~
内容的提问来源于stack exchange,提问作者Struggler
相关产品推荐
相关产品推荐

