Perl отслеживает файл и строку, в которой создается каждый символ. Символ обычно создается, когда парсер / компилятор впервые сталкивается с ним. Но если __DATA__
встречается до того, как DATA
будет создано иначе, это создаст символ. Мы можем воспользоваться этим, чтобы установить номер строки, связанный с дескриптором файла, в DATA
.
Для случая, когда дескриптор Package::DATA
равен , а не , используемый в самом Package.pm
, номер строки токена __DATA__
можно получить через B::GV->LINE
on ручка DATA
:
$ cat Foo.pm
package Foo;
1;
__DATA__
good
bad
$ perl -I. -MFoo -MB -e '
my $ln = B::svref_2object(\*Foo::DATA)->LINE;
warn "__DATA__ at line $ln\n";
Foo::DATA->input_line_number($ln);
while(<Foo::DATA>){ die "no good" unless /good/ }
'
__DATA__ at line 4
no good at -e line 1, <DATA> line 6.
В случае, когда на дескриптор DATA
ссылаются в самом файле, возможный kludge мог бы использовать @INC
hook :
$ cat DH.pm
package DH;
unshift @INC, sub {
my ($sub, $fname) = @_;
for(@INC){
if(open my $fh, '<', my $fpath = "$_/$fname"){
$INC{$fname} = $fpath;
return \'', $fh, sub {
our (%ln, %pos);
if($_){ $pos{$fname} += length; ++$ln{$fname} }
}
}
}
};
$ cat Bar.pm
package Bar;
print while <DATA>;
1;
__DATA__
good
bad
$ perl -I. -MDH -MBar -e '
my $fn = "Bar.pm";
warn "__DATA__ at line $DH::ln{$fn} pos $DH::pos{$fn}\n";
seek Bar::DATA, $DH::pos{$fn}, 0;
Bar::DATA->input_line_number($DH::ln{$fn});
while (<Bar::DATA>){ die "no good" unless /good/ }
'
good
bad
__DATA__ at line 6 pos 47
no good at -e line 6, <DATA> line 8.
Просто для завершения, в случае, если вы делаете , управляющий файлом, все можно легко сделать с помощью:
print "$.: $_" while <DATA>;
BEGIN { our $ln = __LINE__ + 1; DATA->input_line_number($ln) }
__DATA__
...
Вы также можете использовать первое решение B::GV
при условии, что вы ссылаетесь на дескриптор DATA
через eval
:
use B;
my ($ln, $data) = eval q{B::svref_2object(\*DATA)->LINE, \*DATA}; die $@ if $@;
$data->input_line_number($ln);
print "$.: $_" while <$data>;
__DATA__
...
Ни одно из этих решений не предполагает, что исходный файл доступен для поиска (кроме случаев, когда вы хотите прочитать DATA
более одного раза, как я делал во втором примере), или попытаться проанализировать ваши файлы и т. Д.