重新定义或重载反引号

时间:2017-03-08 11:28:32

标签: perl perl5

我有很多遗留代码,我想要做的是添加require或最少的代码更改,以使反引号做一些不同的事情,例如打印而不是运行代码

我尝试使用use subs,但我无法接管反引号或qx(我确实重新定义了一个不用担心的系统)

我也尝试制作一个包:

package thingmbob;
use Data::Dumper;
use overload    '``'    => sub { CORE::print "things!:\t", Dumper \@_};
#this works for some reason
$thingmbob::{'(``'}('ls');
#this does the standard backtick operation
`ls`

不可思议,我没有OOP perl的经验,而且我的google-fu技能让我失望,是否有人能指出我正确的方向?

警告: 我是一个预先安装了几个cpan模块的封闭系统,可能是我没有安装任何花哨的模块而且我绝对无法获得新的模块

我正在使用perl5.14

编辑:

为了完整起见,我想添加我的(大部分)最终产品

BEGIN {
    *CORE::GLOBAL::readpipe = sub {
        print Dumper(\@_);
        @internal = readpipe(@_);
        if(wantarray){
            return @internal;
        }else{
            return join('',@internal);
        }
    };
}

我想让它打印出即将运行的内容,然后运行它。 wantarray很重要,因为没有它标量上下文不起作用

1 个答案:

答案 0 :(得分:8)

perlmonks article解释了如何做到这一点。您可以覆盖内置的readpipe

  

EXPR作为系统命令执行。返回收集的命令标准输出。在标量上下文中,它作为单个(可能是多行)字符串返回。在列表上下文中,返回一个行列表(但是您已使用$/(或$INPUT_RECORD_SEPARATOR中的English)定义了行。这是实现qx/EXPR/运算符的内部函数,但您可以直接使用它。在perlop的I / O操作符中更详细地讨论qx/EXPR/运算符。如果省略EXPR,则使用$_

您需要将其放入BEGIN块中,因此有意义的是不require,而是use而不是尽早使其可用。

使用CORE::GLOBAL:: namespace覆盖内置插件。

BEGIN {
    *CORE::GLOBAL::readpipe = sub {
        print "@_";
    }
}

print qx/ls/;
print `ls`;

输出:

ls1ls1

ls@_,而1是被覆盖子中print的返回值。

或者,有ex::override,它在引擎盖下做同样的事情,但内部不那么奇怪。