gpt4 book ai didi

perl-将 utf8 字节修剪为 'length' 并清理数据

转载 作者:行者123 更新时间:2023-12-04 22:49:30 24 4
gpt4 key购买 nike

我有 utf8 字节序列,需要将其修剪为 30 字节。这可能会导致最后的序列不完整。我需要弄清楚如何删除不完整的序列。

例如

$b="\x{263a}\x{263b}\x{263c}";
my $sstr;

print STDERR "length in utf8 bytes =" . length(Encode::encode_utf8($b)) . "\n";
{
use bytes;
$sstr= substr($b,0,29);
}

#After this $sstr contains "\342\230\272\342"\0
# How to remove \342 from the end

最佳答案

UTF-8 有一些简洁的特性,允许我们在处理 UTF-8 而不是字符时做你想做的事情。所以首先,你需要 UTF-8。

use Encode qw( encode_utf8 );
my $bytes = encode_utf8($str);

现在,在代码点之间拆分。每个代码点的 UTF-8 编码将以匹配 0b0xxxxxxx 的字节开始。或 0b11xxxxxx ,并且您永远不会在代码点的中间找到这些字节。这意味着你想截断之前
[\x00-\x7F\xC0-\xFF]

我们一起得到:
use Encode qw( encode_utf8 );

my $max_bytes = 8;
my $str = "\x{263a}\x{263b}\x{263c}"; # ☺☻☼

my $bytes = encode_utf8($str);
$bytes =~ s/^.{0,$max_bytes}(?![^\x00-\x7F\xC0-\xFF])\K.*//s;

# $bytes contains encode_utf8("\x{263a}\x{263b}")
# instead of encode_utf8("\x{263a}\x{263b}") . "\xE2\x98"

太好了,是吗?不。以上可以在字素的中间截断。字素(特别是“扩展的字素簇”)是人们将其视为单个视觉单元的东西。例如,“é”是一个字素,但它可以使用两个代码点( "\x{0065}\x{0301}" )进行编码。如果在两个代码点之间进行切割,它将是有效的 UTF-8,但“é”将变成“e”!如果这是 Not Acceptable ,则上述解决方案也不是。 (Oleg 的解决方案也遇到了同样的问题。)

不幸的是,UTF-8 的特性不再足以帮助我们。我们需要一次抓取一个字素,并将其添加到输出中,直到我们无法容纳一个为止。
my $max_bytes = 6;
my $str = "abcd\x{0065}\x{0301}fg"; # abcdéfg

my $bytes = '';
my $bytes_left = $max_bytes;
while ($str =~ /(\X)/g) {
my $grapheme = $1;
my $grapheme_bytes = encode_utf8($grapheme);
$bytes_left -= length($grapheme_bytes);
last if $bytes_left < 0;
$bytes .= $grapheme_bytes;
}

# $bytes contains encode_utf8("abcd")
# instead of encode_utf8("abcde")
# or encode_utf8("abcde") . "\xCC"

关于perl-将 utf8 字节修剪为 'length' 并清理数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10953069/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com