【问题标题】:Perl substr based on bytesPerl substr 基于字节
【发布时间】:2012-04-24 16:56:18
【问题描述】:

我正在为我的应用程序使用 SimpleDB。除非一个属性的限制是 1024 字节,否则一切顺利。所以对于长字符串,我必须将字符串切成块并保存。

我的问题是有时我的字符串包含 unicode 字符(中文、日文、希腊文),而 substr() 函数基于字符数而不是字节。

我尝试将use bytes 用于字节语义或更高版本 substr(encode_utf8($str), $start, $length) 但它根本没有帮助。

任何帮助将不胜感激。

【问题讨论】:

  • 您使用的是哪个版本的 perl?

标签: perl utf-8 amazon-simpledb


【解决方案1】:

UTF-8 的设计使字符边界易于检测。要将字符串拆分为有效的 UTF-8 块,您可以简单地使用以下命令:

my $utf8 = encode_utf8($text);
my @utf8_chunks = $utf8 =~ /\G(.{1,1024})(?![\x80-\xBF])/sg;

然后

# The saving code expects bytes.
store($_) for @utf8_chunks;

# The saving code expects decoded text.
store(decode_utf8($_)) for @utf8_chunks;

演示:

$ perl -e'
    use Encode qw( encode_utf8 );

    # This character encodes to three bytes using UTF-8.
    my $text = "\N{U+2660}" x 342;

    my $utf8 = encode_utf8($text);
    my @utf8_chunks = $utf8 =~ /\G(.{1,1024})(?![\x80-\xBF])/sg;

    CORE::say(length($_)) for @utf8_chunks;
'
1023
3

【讨论】:

  • @Borodin,是的,不是的。它不会对正则表达式引擎产生影响,但会对读者产生影响。我们想要匹配上一场比赛停止的地方,所以我们不要隐藏它。
  • @mob,谢谢,但聪明的是 UTF-8 的设计者。他们专门设计了 UTF-8,以便轻松检测字符边界。
【解决方案2】:

substr 对 1 字节字符进行操作,除非该字符串具有 UTF-8 标志。因此,这将为您提供解码字符串的前 1024 个字节:

substr encode_utf8($str), 0, 1024;

虽然,不一定在字符边界上分割字符串。要在最后丢弃任何拆分字符,您可以使用:

$str = decode_utf8($str, Encode::FB_QUIET);

【讨论】:

  • 这不一定会在字符边界上拆分字符串,因此 OP 无法在单个块上调用 decode_utf8(这可能没问题)。
  • 不正确; substr 作用于字符(无论它们的字节大小如何),而不是字节。
  • @mob:他们可以,将Encode::FB_QUIET 作为第二个参数传递。
猜你喜欢
  • 2012-11-16
  • 2013-07-28
  • 2014-09-26
  • 1970-01-01
  • 2014-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多