如何在Perl中找到print语句的源位置?

时间:2009-05-25 00:39:44

标签: perl

如何在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

原因是我试图追踪一些胭脂输出,并且无法在大型代码库中找到它的位置。

8 个答案:

答案 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深入了解代码库中调用的内容。它在内部做了一些非常邪恶的事情,因此不适用于所有代码库。