Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

redefining or overloading backticks

Tags:

perl

I have a lot of legacy code which shells out a lot, what i want to do is add a require or minimal code changes to make the backticks do something different, for instance print instead of running code

i tried using use subs but i couldn't get it to take over backticks or qx (i did redefine system which is one less thing to worry about)

i also tried to make a package:

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`

unfourtunatly, I have no experience in OOP perl and my google-fu skills are failing me, could some one point me in the right direction?

caveat: I'm in a closed system with a few cpan modules preinstalled, odds are that i don't have any fancy modules preinstalled and i absolutely cannot get new ones

I'm on perl5.14

edit:

for the sake of completeness i want to add my (mostly) final product

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

I want it to print what its about to run and then run it. the wantarray is important because without it scalar context does not work

like image 952
Nullman Avatar asked Mar 08 '17 11:03

Nullman


1 Answers

This perlmonks article explains how to do it. You can overwrite the readpipe built-in.

EXPR is executed as a system command. The collected standard output of the command is returned. In scalar context, it comes back as a single (potentially multi-line) string. In list context, returns a list of lines (however you've defined lines with $/ (or $INPUT_RECORD_SEPARATOR in English)). This is the internal function implementing the qx/EXPR/ operator, but you can use it directly. The qx/EXPR/ operator is discussed in more detail in I/O Operators in perlop. If EXPR is omitted, uses $_ .

You need to put this into a BEGIN block, so it would make sense to not require, but use it instead to make it available as early as possible.

Built-ins are overridden using the CORE::GLOBAL:: namespace.

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

print qx/ls/;
print `ls`;

This outputs:

ls1ls1

Where the ls is the @_ and the 1 is the return value of print inside the overridden sub.

Alternatively, there is ex::override, which does the same under the hood, but with less weird internals.

like image 100
simbabque Avatar answered Nov 10 '22 01:11

simbabque