用于从文件中删除UTF-8字符范围的脚本

Chr*_*irt 3 python unicode perl utf-8

我的问题是我有一个包含UTF-8的数据文件,其中大部分是有效的并且必须保留,但其中一些有随机的"垃圾"UTF-8,即在范围内0xf0 - 0xff.下面可以看到坏数据的十六进制示例

 f4 80 80  ab f4 80 80 b6 f4 80 80 
 a5 f4 80 80 a6 f4 80 80  83 f4 80 80 b6 f4 80 81  
 84 f4 80 81 98 f4 80 81  87 f4 80 81 8c f4
Run Code Online (Sandbox Code Playgroud)

我正在尝试编写一个perl脚本,它将搜索并替换第一个字节在该范围内的字符0xf0 - 0xff.在此网站上,代码页被列为私人使用.

我现有的尝试要么什么都不做,要么只能删除多字节字符的第一个字节,例如perl -CSD -pi.orig -e 's/[\x{f4}-\x{ff}]/?/g'Running perl v5.12.5

我不是一个perl专家,也不是一个utf-8专家.我也愿意在ruby/python/C++(98)/中做这件事,只要它在linux盒子上相对便携.

这是一个垃圾数据片段的链接.http://pastebin.com/LR0StPHu

Mar*_*eed 5

好的,我们不要混淆一些事情.

UTF-8字符,其第一个字节长度0xf0为四个字节,这是您编写合法Unicode字符所需的最多字符.由于超过94%的可能Unicode范围需要第四个字节,因此0xf0不会映射到任何单个代码页,当然也不会映射到私有使用区域.

这些字符基本多文种平面.但这与无效或私人使用不同; 它只是意味着他们的代码点大于U + FFFF(十进制值65,535).

如果要排除BMP之外的所有字符,您应该搜索与此正则表达式匹配的字符:

[\x{10000}-\x{10FFFF}]
Run Code Online (Sandbox Code Playgroud)

它使用Perl的\x{... }插值语法按十六进制代码点值包含字符.如果您实际上正在使用Perl,那么为了易于使用,您可能希望将正则表达式放入变量中(使用quote-regex构造qr(... ),因为裸斜杠将立即尝试$_在赋值时匹配正则表达式):

my $not_bmp = qr([\x{10000}-\x{10FFFF}]);
Run Code Online (Sandbox Code Playgroud)

但是,再次删除匹配该正则表达式的字符可以消除超过94%的可能Unicode字符,因此请确保这是您想要的.

如果你真的只是想消除私人使用的字符-其中一些是内部的BMP -只需排除这些范围明确.使用Perl或Python或任何其他支持UTF-8的语言,您不必担心字节; 只需检查代码点.

正如维基百科将告诉您的那样,三个私有使用区域在这些代码点范围内:

  • U + E000..U + F8FF
  • U + F0000..U + FFFFF
  • U + 100000..U + 10FFFF

所以相应的Perl正则表达式如下所示:

my $pua = qr([\x{e000}-\x{f8ff}\x{f0000}-\x{fffff}\x{100000}-\x{10ffff}]);
Run Code Online (Sandbox Code Playgroud)

许多其他语言具有类似的Unicode支持(与UTF-8字符匹配,包括按代码点的字符串中的字符,依此类推).例如,这里是Ruby,它主要区别于使用\u{...}而不是\x{...}插值:

not_bmp = %r([\u{10000}-\u{10FFFF}])
pua = %r([\u{e000}-\u{f8ff}\u{f0000}-\u{fffff}\u{100000}-\u{10ffff}])
Run Code Online (Sandbox Code Playgroud)

Python的\u转义只有正好四个十六进制数字的工作,但如果你有Python3 -或Python2编译模式-您可以使用资本\U,这恰恰是八(有没有通过可变长度的支持{...... }像Perl和Ruby有) :

not_bmp = re.compile(u'[\U00010000-\U0010ffff]')
pua = re.compile(u'[\ue000-\uf8ff\U000f0000-\U000fffff\U00100000-\U0010ffff]')
Run Code Online (Sandbox Code Playgroud)

  • 听起来像沿途的东西并不真正支持UTF-16,但只支持UCS-2.无论如何,很高兴我能帮忙. (2认同)