如何用Perl正则替换字符串中的无效UTF-8字符
Perl替换无效UTF-8字符方案
基于你现有的UTF-8验证正则,要替换无效字符,核心思路是跳过所有有效UTF-8序列,只匹配并替换剩下的无效内容。以下是实现代码:
use strict; use warnings; use utf8; # 自定义替换的有效UTF-8字符,可根据需求修改 my $replacement_char = '�'; my @Strings = ( 'Caractéristiques techniques', # 含无效单字节和不完整多字节序列的测试字符串 'Test with invalid: ' . "\xFF" . ' | broken seq: ' . "\xE0\x80", 'Out-of-range 4-byte: ' . "\xF5\x80\x80\x80" ); foreach my $ival (@Strings) { # 原验证逻辑 my $is_valid = eval { $ival =~ /\A( [\x00-\x7F] # ASCII单字节 | [\xC2-\xDF][\x80-\xBF] # 非过长的双字节序列 | \xE0[\xA0-\xBF][\x80-\xBF] # 排除过长的三字节序列 | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # 标准三字节序列 | \xED[\x80-\x9F][\x80-\xBF] # 排除代理对 | \xF0[\x90-\xBF][\x80-\xBF]{2} # 1-3平面四字节序列 | [\xF1-\xF3][\x80-\xBF]{3} # 4-15平面四字节序列 | \xF4[\x80-\x8F][\x80-\xBF]{2} # 16平面四字节序列 )*\z/x }; print "原字符串: $ival\n"; if ($is_valid) { print " -> 有效UTF-8,无需替换\n"; } else { # 替换所有无效内容 my $cleaned_str = $ival; $cleaned_str =~ s/( [\x00-\x7F] | [\xC2-\xDF][\x80-\xBF] | \xE0[\xA0-\xBF][\x80-\xBF] | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} | \xED[\x80-\x9F][\x80-\xBF] | \xF0[\x90-\xBF][\x80-\xBF]{2} | [\xF1-\xF3][\x80-\xBF]{3} | \xF4[\x80-\x8F][\x80-\xBF]{2} )(*SKIP)(*FAIL)|./$replacement_char/gx; print " -> 无效UTF-8,清理后字符串: $cleaned_str\n"; } print "\n"; }
关键逻辑说明
- 复用你原有的有效UTF-8序列正则,通过
(*SKIP)(*FAIL)标记这些有效序列,让正则引擎跳过它们,不进行替换。 |.匹配所有未被标记的单个无效字节,全局替换为你指定的有效字符。- 如果需要将连续的无效字节合并成一个替换字符,可把替换正则中的
|.改为|.+,即s/...|.+/$replacement_char/gx。
内容的提问来源于stack exchange,提问作者Chazg76
相关产品推荐
相关产品推荐

