如何在Perl中找到print语句的源位置?
#!/usr/bin/perl
foo();
bar();
sub foo {
print "foo\n";
}
sub bar {
print "bar\n";
}
输出为:
>perl test.pl
foo
bar
我想以某种方式找到能够看到(或类似的东西)
>perl test.pl
main::foo> foo
main::bar> bar
原因是我试图追踪一些胭脂输出,并且无法在大型代码库中找到它的位置。
答案 0 :(得分:15)
试试这个:
#!/usr/bin/env perl
use strict;
use warnings;
use Tie::STDOUT print => sub {
my ( $pkg, $file, $line ) = caller(2);
print "$pkg, $file, $line :: ", @_;
};
print "Hello, World\n";
给出了:
$ perl tp.pl
main, tp.pl, 10 :: Hello, World
更新:我刚刚发布了Devel::Ditto:
$ perl -MDevel::Ditto myprog.pl
[main, t/myprog.pl, 9] This is regular text
[main, t/myprog.pl, 10] This is a warning
[MyPrinter, t/lib/MyPrinter.pm, 7] Hello, World
[MyPrinter, t/lib/MyPrinter.pm, 8] Whappen?
答案 1 :(得分:8)
使用Debug :: Trace(https://metacpan.org/pod/Debug::Trace)
#!/usr/bin/perl
foo();
bar();
sub foo {
print "foo\n";
}
sub bar {
print "bar\n";
}
此程序保存为test.pl并称为:
perl -MDebug::Trace=foo,bar test.pl
打印出来:
TRACE: main::foo() called at test.pl line 3 package main
foo
TRACE: main::foo() returned
TRACE: main::bar() called at test.pl line 4 package main
bar
TRACE: main::bar() returned
答案 2 :(得分:5)
我知道源过滤器可能对某些内容有用:
C:\Temp> cat DebugFilter.pm
package DebugFilter;
use strict;
use warnings;
use Filter::Simple;
FILTER_ONLY
code_no_comments => sub {
s/print/main::mydebugfn();print/g
};
1;
__END__
C:\Temp> cat DebugPrint.pm
package DebugPrint;
use strict;
use warnings;
use base qw( Exporter );
our @EXPORT = qw( mydebugfn );
sub mydebugfn {
my ( $pkg, $fn, $line, $sub ) = caller(2);
warn "print called from: ${sub}(${fn}:${line})\n";
}
1;
__END__
C:\Temp> cat t.pl
#!/usr/bin/perl
use strict;
use warnings;
use DebugFilter;
sub test {
print STDOUT "print in test\n";
return;
}
test();
这是输出:
C:\Temp> perl -MDebugPrint t.pl
print called from: main::test(t.pl:13)
print in test
答案 3 :(得分:4)
Copas:我不能直接回复你的评论(还不够“酷”),但基本问题是任何体面的项目都不是一个.pl文件。它是一堆模块,所有模块都被拉在一起。
您的代码:
a)不解决一个.pl文件之外的任何内容 b)不处理印刷品(...)有支架或不同间距的情况。 c)不处理print的第一个参数是函数调用或变量而不是双引号字符串的情况。 d)考虑:$ object-> log(“我要打印”.foo($ var)。“到控制台”); - 你的正则表达式会导致语法错误,使得:$ object-> log(“即将打印”第1084行:。$ foo($ var)。“到控制台”);
也就是说,它对于简单的脚本是可行的。这不是一个坏主意(最糟糕的情况是,你的newsource.pl没有编译) - 但它不会解决这个特殊问题,除非它只在一个文件中。
答案 4 :(得分:4)
本文介绍如何挂钩perl打印功能: How can I hook into Perl's print?
如果您不想用其他内容替换源代码中的所有print语句,则可能需要它。
答案 5 :(得分:4)
我将保留源过滤器替代品以供参考,因为它适用于跟踪单个函数的调用。
但是,解决方案似乎是使用Devel::Trace。这可能会生成大量输出,您可以将其重定向到文件,然后grep以查找有问题的输出。
C:\Temp> perl -d:Trace t.pl
>> t.pl:10: T::test();
>> T.pm:5: print "in T::test\n";
in T::test
>> c:/opt/perl/lib/Config.pm:63: sub DESTROY { }
答案 6 :(得分:3)
您可以尝试使用调试器(perl -d)逐步执行代码。
我打算建议覆盖打印并使用:
($package, $filename, $line) = caller;
...打印出额外的信息,但事实证明print是无法覆盖的内置内容之一。
答案 7 :(得分:1)
您可以尝试使用Hook::LexWrap深入了解代码库中调用的内容。它在内部做了一些非常邪恶的事情,因此不适用于所有代码库。