如何重新定义内置的Perl函数?

如何重新定义内置的Perl函数?,perl,redefine,Perl,Redefine,我想做两件事: 在生产代码中,我想重新定义open命令,使我能够添加automatic文件日志记录。我从事数据处理应用程序/流程的工作,作为其中的一部分,用户必须准确了解正在处理的文件。如果他们使用的是旧版本的文件,他们可以通过阅读正在处理的文件列表来找到 我可以创建一个新的子文件来记录日志,并返回一个文件指针,然后在代码中用它代替open 如果我能重新定义open并从这个行为中获得已有代码的好处,那就太好了。我能做这个吗 在调试代码中,我想重新定义printf命令,以插入注释以及指示生成该行的

我想做两件事:

在生产代码中,我想重新定义open命令,使我能够添加automatic文件日志记录。我从事数据处理应用程序/流程的工作,作为其中的一部分,用户必须准确了解正在处理的文件。如果他们使用的是旧版本的文件,他们可以通过阅读正在处理的文件列表来找到

我可以创建一个新的子文件来记录日志,并返回一个文件指针,然后在代码中用它代替open

如果我能重新定义open并从这个行为中获得已有代码的好处,那就太好了。我能做这个吗


在调试代码中,我想重新定义printf命令,以插入注释以及指示生成该行的代码的书面输出。同样,我有一个sub可以选择这样做,但是转换我现有的代码是很乏味的。

对于open:这对我来说很有效

use 5.010;
use strict;
use warnings;
use subs 'open';
use Symbol qw<geniosym>;

sub open (*$;@) { 
    say "Opening $_[-1]";
    my ( $symb_arg ) = @_;
    my $symb;
    if ( defined $symb_arg ) { 
        no strict;
        my $caller = caller();
        $symb = \*{$symb_arg};
    }
    else { 
        $_[0] = geniosym;
    }
    given ( scalar @_ ) { 
        when ( 2 ) { return CORE::open( $symb // $_[0], $_[1] ); }
        when ( 3 ) { return CORE::open( $symb // $_[0], $_[1], $_[2] ); }
    }
    return $symb;
}

open PERL4_FH, '<', 'D:\temp\TMP24FB.sql';
open my $lex_fh, '<', 'D:\temp\TMP24FB.sql';
使用5.010;
严格使用;
使用警告;
使用SUB“打开”;
使用符号qw;
子打开(*$;@){
说“期初$\[-1]”;
我的($symb_arg)=@;
我的$symb;
如果(定义为$symb_arg){
不严格;
my$caller=caller();
$symb=\*{$symb\u arg};
}
否则{
$u0]=geniosym;
}
给定(标量){
当(2){returncore::open($symb/$\[0],$\[1]);}
当(3){returncore::open($symb/$\u0],$\u1],$\u2])}时
}
返回$symb;
}

如果核心子例程具有原型,则打开PERL4_FH,,可以替换它。在当前名称空间中替换函数非常简单

#!/usr/bin/perl

use strict;
use warnings;

use subs 'chdir';

sub chdir(;$) {
    my $dir = shift;
    $dir    = $ENV{HOME} unless defined $dir;
    print "changing dir to $dir\n";
    CORE::chdir $dir;
}

chdir("/tmp");
chdir;
如果您想覆盖所有模块的功能,您可以阅读

*
下面是测试Perl 5.10中每个函数的代码(它也适用于早期版本)。注意,有些函数可以被重写,但该程序会告诉您不能被重写,但被重写的函数的行为方式与原始函数不同

来自perldoc-f原型

如果内置项不可重写 (如qw/)或如果其参数 不能用一个 原型(如系统), prototype()返回undf,因为 builtin的行为并不像 Perl函数

#/usr/bin/perl
严格使用;
使用警告;
对于我的$func(映射{split}){
我的$proto;
#跳过不在此版本的Perl中的函数
下一步除非eval{$proto=prototype“CORE::$func;1};
如果($proto){
打印“$func的原型为$proto\n”;
}否则{
打印“$func不能被覆盖\n”;
}
}
__资料__
abs在2绑定时接受报警
binmode bless break调用程序chdir
chmod CHONP chop CHON chr
chroot关闭closedir连接继续
cos crypt dbmclose定义的删除
把每一个垃圾都倒进去
endhostent endnetent endprotoent endpwent endservent
eof eval exec存在并退出
exp fcntl文件无植绒叉
格式化formline getc getgrent getgrgid
getgrnam gethostbyaddr gethostbyname gethostent getlogin
getnetbyaddr getnetbyhost getnetent getpeername getpgrp
getppid getpriority getprotobyname getprotobynumber getprotoent
getpwent getpwnam getpwuid getservbyname getservbyport
getservent getsockname getsockopt glob gmtime
转到grep十六进制导入索引
int ioctl连接键终止
最后一个链路长度和第一个链路长度
侦听本地本地时间锁日志
lstat m地图mkdir msgctl
msgget msgrcv msgsnd我的下一个
无oct open DIR ord
我们的包装烟斗
pos打印打印原型推送
qq qr报价表qw
qx rand read DIR readline
readlink readpipe recv redo ref
重命名需要重置返回反向
rewinddir rindex rmdir s说
标量搜索seekdir选择semctl
semget semop发送setgrent sethostent
setnetent setpgrp setpriority setprotoent setpwent
setservent setsockopt shmctl shmget换档开关
shmread shmwrite在睡眠中关闭
插座插座对分类拼接拆分
sprintf sqrt和状态
研究子substr符号链接系统调用
sysopen sysread sysseek系统syswrite
告诉泰尔迪尔打领带的时间
乘以tr首先截断uc
umask undef取消链接解包取消提升
释放使用utime值vec
等待WAITARY warn写入
y-r-w-x-o
-R-W-X-O-e
-z-s-f-d-l
-p-S-b-c-t
-u-g-k-T-B
-M-A-C

它告诉我chomp不能被重写,但它仍然有效
#!/usr/bin/perl

use strict;
use warnings;

for my $func (map { split } <DATA>) {
    my $proto;
    #skip functions not in this version of Perl
    next unless eval { $proto = prototype "CORE::$func"; 1 };
    if ($proto) {
        print "$func has a prototype of $proto\n";
    } else {
        print "$func cannot be overridden\n";
    }
}

__DATA__
abs          accept         alarm          atan2            bind          
binmode      bless          break          caller           chdir
chmod        chomp          chop           chown            chr
chroot       close          closedir       connect          continue
cos          crypt          dbmclose       defined          delete
die          do             dump           each             endgrent 
endhostent   endnetent      endprotoent    endpwent         endservent
eof          eval           exec           exists           exit
exp          fcntl          fileno         flock            fork
format       formline       getc           getgrent         getgrgid
getgrnam     gethostbyaddr  gethostbyname  gethostent       getlogin
getnetbyaddr getnetbyhost   getnetent      getpeername      getpgrp
getppid      getpriority    getprotobyname getprotobynumber getprotoent
getpwent     getpwnam       getpwuid       getservbyname    getservbyport
getservent   getsockname    getsockopt     glob             gmtime
goto         grep           hex            import           index
int          ioctl          join           keys             kill
last         lc             lcfirst        length           link
listen       local          localtime      lock             log
lstat        m              map            mkdir            msgctl
msgget       msgrcv         msgsnd         my               next
no           oct            open           opendir          ord
our          pack           package        pipe             pop
pos          print          printf         prototype        push
q            qq             qr             quotemeta        qw
qx           rand           read           readdir          readline
readlink     readpipe       recv           redo             ref
rename       require        reset          return           reverse
rewinddir    rindex         rmdir          s                say
scalar       seek           seekdir        select           semctl
semget       semop          send           setgrent         sethostent
setnetent    setpgrp        setpriority    setprotoent      setpwent
setservent   setsockopt     shift          shmctl           shmget
shmread      shmwrite       shutdown       sin              sleep
socket       socketpair     sort           splice           split
sprintf      sqrt           srand          stat             state
study        sub            substr         symlink          syscall
sysopen      sysread        sysseek        system           syswrite
tell         telldir        tie            tied             time
times        tr             truncate       uc               ucfirst
umask        undef          unlink         unpack           unshift
untie        use            utime          values           vec
wait         waitpid        wantarray      warn             write
y            -r             -w             -x               -o
-R           -W             -X             -O               -e
-z           -s             -f             -d               -l
-p           -S             -b             -c               -t
-u           -g             -k             -T               -B
-M           -A             -C