Perl中的Substr,将utf8字符减半

Perl中的Substr,将utf8字符减半,perl,substr,Perl,Substr,在PerlV5.8.5中使用substr时,我试图找出一个问题。下面是一个示例字符串: UTF-8示例いろはにほξεσκεπζωff 似乎被削减到: UTF-8示例いろはにほξεσκε�... 在代码中,我看到一条关于宽字符的消息。我想知道是不是substr把这个词一分为二?如果我删除代码中的substr()部分,则字符串显示良好 我以前从未在utf8中遇到过这种情况。我们需要用阿拉伯语字符做些特殊的事情吗 更新:如果我检查前后字符串的长度,似乎确实发生了一些奇怪的事情: 测试:UTF-8示例い

在PerlV5.8.5中使用
substr
时,我试图找出一个问题。下面是一个示例字符串:

UTF-8示例いろはにほξεσκεπζωff

似乎被削减到:

UTF-8示例いろはにほξεσκε�...

在代码中,我看到一条关于宽字符的消息。我想知道是不是
substr
把这个词一分为二?如果我删除代码中的
substr()
部分,则字符串显示良好

我以前从未在utf8中遇到过这种情况。我们需要用阿拉伯语字符做些特殊的事情吗

更新:如果我检查前后字符串的长度,似乎确实发生了一些奇怪的事情:

测试:UTF-8示例いろはにほξεσκεπάζω
长度:63 长度:67后

我只是不知道是什么!FWIW,我在脚本的标题中也使用了这个:

use utf8;

谢谢

通常情况下,我现在已经找到了一个解决方法。它不是超级漂亮,但似乎很管用

use Unicode::String qw(utf8);

$us = utf8($hit->{post_title});
if ($us->length > 30) {
    $hit->{post_title} = $us->substr(0,30);
}
因此,基本上将utf8字符串粘贴到Unicode::string中,然后如果它超过给定的大小,则将其修剪并传递回
$hit->{post_title}
。这不漂亮,但很管用


不幸的是,这是一个过时(2000年!)的软件,所有者(慈善机构)不想升级到更好的论坛软件。我试着说服他有一段时间了,但这是不可能的。这会让我无法继续为他“更新”它,因为即使是开箱即用的代码也是一团糟。无论如何,这似乎是一场胜仗:)

可以试试这个
使用open':encoding(utf8)';双模式标准输出':utf8'
@ssr1012-谢谢,但这似乎让情况变得更糟(破坏了编码:
UTF-8示例××××××××××××××ãã«ã»ÎÎλλÎÎÎϻλÏÏ
)您的字符串来自哪里?如果是从文件中读取数据,则在读取文件时需要将数据解码为Perl字符。如果它是源代码的一部分,则需要将
使用utf8
添加到程序中,以便Perl知道它是UTF-8。在这两种情况下,您都希望在打印字符之前将字符编码为UTF-8,并告诉输出文件句柄需要UTF-8数据。请参阅(perlunitut)[了解详细信息。另外,如果您能提供一个完整的可运行示例来说明问题,那将是一件好事。@DaveCross谢谢。我设法找到了一个使用
Unicode::String
的解决方法。这个脚本的问题是它太可怕了(它是一个非常古老的BBS类型系统).我不知道那家伙写这本书的时候抽的是什么,但它的结构很糟糕。无论如何,它还有一天会死:)我怀疑这只是我们在对你的问题的评论中提出的建议的一个薄薄的包装。@DaveCross-可能是的。鉴于我为他免费做这件事,我真的不想花很多时间调试它。我已经花了几个小时在上面,还有其他地方可以“修复”它。我已经解释过,他真的需要看看比2000年更新一点的东西,使它更新(他认为在旧软件上更安全,但我不同意!)这不是一个解决方法。这是您的操作方式。Perl有两种类型的字符串:ASCII和UTF-8。在OP的代码中,字符串在ASCII字符串中包含UTF-8字符。正确的解决方案是将其转换为UTF-8字符串。这就是您的操作方式。@shawnhcorey:Perl没有ASCII字符串和UTF-8字符串。它有二进制字符串(假设所有字符都是单字节)和文本字符串(不符合该假设)。如果您有幸处理所有字符都是单字节的数据,那么您可能有IS0-8859-1(也称为“拉丁-1”),而不是ASCII。有很多方法可以在这两种类型的字符串之间进行转换。Unicode::string是比较模糊的一种。@DaveCross如果您想将其称为二进制,这很好,但编码可能是任意的,因此假设它是ASCII,则意味着您会犯更少的错误。并且所有字符串上都有一个标志,指示它是UTF-8。如果滞后是关闭的,它是一个二进制字符串。如果它打开,它是UTF-8。
use Unicode::String qw(utf8);

$us = utf8($hit->{post_title});
if ($us->length > 30) {
    $hit->{post_title} = $us->substr(0,30);
}