我决定发布一个问题,花了很长时间后仍然没有弄清问题。还阅读了一堆看似相关的帖子,没有一个真的适合我的简单(?)问题。
所以我有一个可能很大的文本文件(> 1000行),其中包含普通话中文字符,其示例行如下:
"ref#2-5-1.jpg#2#一些 <variable> 内容#pic##" (the Chinese just means "some content").
所有需要修改的是,如果没有一个空格,应该在每个角色之间插入一个空格:
"ref#2-5-1.jpg#2#一 些 <variable> 内 容#pic##".
我开始天真地用以下简单的东西,但根本没有匹配:
sed -e 's/\([\u4E00-\u9fff]\)/\1 /g' <test_utf_sed.txt > test_out.txt
其中4E00-9fff应该是普通话的代码范围。 毫无疑问,这没有用,所以我也想尝试
sed -e 's/\([一-龻]\)/hello/g' <test_utf_sed.txt > test_out.txt
这失败了,因为我的bash无法显示(?)“一”字符。
然后我做了一些基本测试,但也失败了:
sed -e 's/\(\u4E00\)/hello/g' <test_utf_sed.txt > test_out.txt //一
sed -e 's/\(\u4E9B\)/hello/g' <test_utf_sed.txt > test_out.txt //些
与utf编码的另一种表示法相同(在stackoverflow上找到):
sed -e 's/\(\u'U+4E00\)/hello/g' <test_utf_sed.txt > test_out.txt
1)作为处理双字节字符的工具,可以选择正确的选择吗?
2)是否能够完全处理unicode,还是需要一个特殊的开关?
3)我不正在寻找这样的解决方案:
step1: insert space after each character
//like 's/\(.\)/\1 /g')
step2: remove space after each chacter which is not a Chinese character
//like 's/\([a-zA-Z0-9]\) /\1/g')
我知道如何做到这一点,但它不够优雅且容易出错。这必须可以在sed中使用正则表达式中的utf-8。
4)我的环境在 MacOS 10.6.8 (旧式操作系统)上 bash-3.2 。
5)如果您知道某些开放的regEx-onliners指向中文文本或语言处理的库,那么分享会很棒。
非常感谢您,非常感谢您的帮助!
答案 0 :(得分:5)
Perl对处理Unicode有很好的支持。对于你的任务而言,这可能比sed更好。这个单行程就像你的第一个sed示例一样:
perl -CIOED -p -e 's/\p{Block=CJK_Unified_Ideographs}/$& /g' filename
-CIOED
告诉perl在utf8中执行其I / O. -p
为输入文件的每一行运行给定代码一次,然后打印结果。 -e
指定要运行的一行Perl代码。有关更多信息,请参阅命令行参数的the documentation。
正则表达式使用named ranges来标识要匹配的字符。
您可能还想阅读Perl Unicode文档。
答案 1 :(得分:2)
sed
并不了解\u
转义序列(显然)。我不知道bash-3.2是否也有,但我认为确实如此;如果是这样,你可以写
sed $'s/\u4E9B/hello/g'
但你仍然无法进行范围规范。
但是,通过手动翻译为UTF-8,您可以得到以下扩展正则表达式,我相信,它将匹配U +范围内某个字符的任何UTF-8序列4E00 ... U + 9FFF:
(\xe4[\xb8-\xbf][\x80-\xbf]|[\xe5-\xe9][\x80-\xbf][\x80-\xbf])
(但是只有在单字节语言环境中调用sed
时,字符范围才有效,最好是C
语言环境。)
使用GNU sed
,如果提供-r
标志,则会获得扩展的正则表达式。使用MacOSX,我相信你需要-E
标志。所以你可以试试:
LANG=C sed -E \
$'s/(\xe4[\xb8-\xbf][\x80-\xbf]|[\xe5-\xe9][\x80-\xbf][\x80-\xbf])/\\1 /g' \
<test_utf_sed.txt >test_out.txt
(上面让bash处理\x
转义。如果你忽略了$
,那么sed
将会处理\x
转义,但是你会必须将替换从\\1
更改为\1
。我没有Mac,也没有旧版本的bash,所以我真的不知道你的{{{ 1}}十六进制是否逃脱;我非常确定你的bash会,但我无法保证。)
顺便说一句,对这些角色进行utf-8编码并不困难;我用原始帖子中的一些复制粘贴做了。例如:
sed
有助于知道平面0表意文字(U + 4E00 ... U + 9FFF)的整个范围都有三字节代码,因此一个是$ hd <<<"一些"
00000000 e4 b8 80 e4 ba 9b 0a |.......|
而一些是E4 B8 80
。 (E4 BA 9B
当然是一个行尾。)