regex - Perl:从文件中间读取时如何避免正则表达式 UTF-8 错误

标签 regex perl utf-8

在查找后读取 utf8 编码的文件,如 open(FILE, '<:utf8', $file) or die; seek(FILE, $readFrom, 0); read(FILE, $_, $size); 所示有时会“分解”unicode 字符,因此读取的字符串的开头不是有效的 UTF-8。

如果你然后这样做s{^([^\n]*\r?\n)}{}i要删除不完整的第一行,您会收到“格式错误的 UTF-8 字符(致命)”错误。

如何解决这个问题?

一个解决方案,列于 How do I sanitize invalid UTF-8 in Perl?是删除所有无效的 UTF-8 字符:

tr[\x{9}\x{A}\x{D}\x{20}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}][]cd;

但是,搜索整个字符串似乎有点矫枉过正,因为只有读取字符串中的第一个字节可以被破坏。

任何人都可以建议一种方法来仅删除初始无效字符(或使上述替换不会在格式错误的 UTF-8 上消失)吗?

最佳答案

以字节形式读取流,去掉开头的部分字符,确定最后一个完整字符的结束位置,然后解码剩下的内容。

use Encode qw( STOP_AT_PARTIAL );
use Fcntl  qw( SEEK_TO );

my $encoding = Encode::find_encoding('UTF-8');

open(my $FILE, '<:raw', $file) or die $!;
seek($FILE, $readFrom, SEEK_TO) or die $!;
my $bytes_read = read($FILE, my $buf, $size);
defined($bytes_read) or die $!;

$buf =~ s/^[\x80-\xBF]+//;

my $str = $encoding->decode($buf, STOP_AT_PARTIAL);

如果您想阅读更多内容,请使用 read 的 4-arg 形式,并且这次不要在开始时跳过任何内容。

my $bytes_read = read($FILE, $buf, $size, length($buf));
defined($bytes_read) or die $!;

$str .= $encoding->decode($buf, STOP_AT_PARTIAL);

相关阅读:Convert UTF-8 byte stream to Unicode

关于regex - Perl:从文件中间读取时如何避免正则表达式 UTF-8 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33475249/

相关文章:

regex - 如何用 Go regexp 中的计数器替换出现的字符串?

perl - 如何让 Perl 检测错误的 UTF-8 序列?

mysql - Adminer 和 phpmyadmin 的 UTF-8 输入问题

android - 如何在 Android 中使用正则表达式运行查询

java - 如何从字符串中提取括号数据

java - 将文件名分成组

mysql - 如何生成下一个请求 ID

perl - 调用 perl 脚本

perl - 递归网络爬虫 perl

c++ - 如何使用 UTF-8 编码将 LPWSTR 转换为 char *