如何覆盖Perl中的`length`子程序?

时间:2015-05-23 20:00:57

标签: perl

我想简单地覆盖length子程序以考虑ANSI转义序列,所以我写了这个:

sub length {
    my $str = shift;
    if ($cfg{color}) {
        return length($str =~ s/\x1B\[\d+[^m]*m//gr);
    } 
    return length($str);
}

不幸的是,Perl检测到使用CORE::length重新进行的模糊调用。

我怎样才能告诉Perl使用本地声明呢?

当然,另一种解决方案是使用length将每次调用重命名为ansi_length并相应地重命名自定义函数。

对于那些想要更多细节的人:

我想覆盖核心模块length的上下文是一个生成ASCII表的简短代码(有点像Text::ASCIITable,但具有不同的功能,如多列和多行)。我不想编写一个专用的Perl模块,因为我希望尽可能保持我的程序是单片的,因为使用它的人不熟悉CPAN甚至模块安装。

在此代码中,我需要知道每行中每列的宽度,以便正确对齐它们。当单元格包含带有^[[33mgreen^[[0m等ANSI序列的彩色文本时,我需要忽略着色序列。

由于我已在程序中使用UTF-8字符,因此我必须将其添加到我的程序中:

use utf8;
use open ':std', ':encoding(UTF-8)';

我注意到utf8模块也会重载核心子例程length。我意识到这对我来说也是一个很好的解决方案。

最后我想我在这个问题上添加了足够的细节。我很高兴得到通知,为什么我对这个问题有所了解。我不认为我能说得更清楚。此外,我认为所有这些细节都无法理解最初的问题......

1 个答案:

答案 0 :(得分:7)

覆盖核心功能不是一个好主意。如果您使用库,那么它本身使用核心函数,库函数将面临覆盖函数并可能失败。你可以创建一个自己的模块/命名空间ANSI ::或者..然后使用ANSI :: length,但我认为使用你提出的名称是更好的:ansi_length。

如果你还坚持: 您可以使用

覆盖核心功能
BEGIN {
  *CORE::GLOBAL::length = sub ... 
}

每当您需要访问原始CORE功能时,请使用 CORE ::长度。

这适用于Perl的所有内置函数。

以下是参考:http://perldoc.perl.org/CORE.html