Как найти исходное местоположение оператора печати в Perl? - PullRequest
9 голосов
/ 25 мая 2009

Как найти исходное местоположение оператора печати в Perl?

#!/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 ]

15 голосов
/ 25 мая 2009

Попробуйте это:

#!/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?
8 голосов
/ 25 мая 2009

Использовать 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
5 голосов
/ 25 мая 2009

Я знал, что исходные фильтры могут быть полезны для чего-то:

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
4 голосов
/ 25 мая 2009

Я собираюсь оставить исходный фильтр альтернативным для справки, поскольку он направлен на отслеживание вызова одной функции.

Однако решение, похоже, заключается в использовании 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 { }
4 голосов
/ 25 мая 2009

В этой статье объясняется, как подключиться к функции печати Perl: Как я могу подключиться к печати Perl?

Он может вам понадобиться, если вы не хотите заменять все операторы печати в вашем исходном коде чем-то другим.

4 голосов
/ 25 мая 2009

Copas: Я не могу ответить на ваш комментарий напрямую (пока не достаточно "круто"), но основная проблема в том, что любой проект приличного размера - это не один файл .pl. Это куча модулей, которые все собираются вместе.

Ваш код:

a) не обращается ни к чему, кроме одного файла .pl б) не обрабатывает случаи, когда print (...) имеет скобки или другой интервал. в) не справляется со случаями, когда первым аргументом для печати является вызов функции или переменная, а не строка в двойных кавычках. d) рассмотрим: $ object-> log («Я собираюсь напечатать». foo ($ var). «на консоль»); - Ваше регулярное выражение вызовет синтаксическую ошибку, сделав следующее: $ object-> log (строка «Я собираюсь напечатать», строка 1084:. $ foo ($ var). «to the console»);

Тем не менее, это жизнеспособно для простых сценариев. Это не ПЛОХАЯ идея (в худшем случае, ваш newsource.pl не компилируется) - но эта конкретная проблема не будет исправлена, если только она не будет в одном файле.

3 голосов
/ 25 мая 2009

Вы можете попробовать пройтись по коду с помощью отладчика (perl -d).

Я собирался предложить переопределить печать и использовать:

($package, $filename, $line) = caller;

... чтобы распечатать дополнительную информацию, но оказывается, что печать - это одна из встроенных функций, которую нельзя переопределить.

1 голос
/ 25 мая 2009

Вы можете попробовать использовать Hook :: LexWrap , чтобы разобраться, что вызывает то, что в вашей кодовой базе. Он делает некоторые довольно злые вещи внутри, поэтому не будет работать для всех кодовых баз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...