File::Find
和想要的子程序
这个问题比原始标题(“原型和子程序的前向声明”!)简单得多.我希望答案,无论多么简单,都能帮助我理解子程序/函数,原型和作用域以及File :: Find模块.
使用Perl,子程序几乎可以出现在任何地方,你通常不需要进行前向声明(除非sub声明了一个原型,我不知道如何在Perl中采用“标准”方式).对于我通常使用Perl做的事情,运行某些功能的这些不同方式之间没有什么区别:
sub somefunction; # Forward declares the function &somefunction; somefunction(); somefunction; # Bare word warning under `strict subs`
我经常使用find2perl
来生成代码,我将这些代码整合到脚本的一部分中.这可能是糟糕的风格,现在我的脏衣服是公开的,但所以它:-) For File ::找到想要的功能是一个必需的子程序 – find2perl创建它并添加sub想要的;到它创建的结果脚本.有时候,当我编辑脚本时,我会从子通缉中删除“sub”,它最终会成为& wanted;或想要();.但没有潜艇通缉;转发申报表我收到此警告:
Use of uninitialized value $_ in lstat at findscript.pl line 29
我的问题是:为什么会发生这种情况,这是一个真正的问题吗?这只是“警告”,但我想更好地理解它.
>文档和代码说$_是在sub wanted {}内部本地化的.如果我使用wanted(),为什么不定义?而不是想要的;?
>是否想在某处使用原型?我在Find / File.pm中遗漏了一些明显的东西吗?
>是因为想要返回代码引用吗? (???)
我的猜测是前向声明表单“初始化”需要某种方式,以便第一次使用没有空的默认变量.我想这就是原型 – 即使Perl原型,如它们存在 – 也会起作用.我尝试使用Perl源代码来深入了解当使用子函数而不是function()调用函数时子正在做什么,但这可能超出了我的目的.
任何帮助深化(并加快)我对此的理解都非常感谢.
编辑:这是我用find2perl的输出创建的recent example script here on StackOverflow.如果你从sub想要删除sub;你应该得到同样的错误.
编辑:正如我在下面的评论中提到的(但我也会在这里标记):几个月来我一直在使用Path::Iterator::Rule
而不是File :: Find.它需要perl> 5.10,但我永远不必在具有奇怪的“永不升级”,5.8.*的策略的站点部署生产代码,因此Path :: Iterator :: Rule已成为我从未想过的模块之一出.同样有用的是Path::Class
.干杯.
解决方法
我所做的是在我的find命令中内联我想要的子程序.子程序保留在查找中.另外,我的非本地数组变量现在只是我的find命令的一部分,看起来并不那么糟糕
这是我处理File :: Find的方式 – 假设我想要带有.pl后缀的文件:
my @file_list; find ( sub { return unless -f; #Must be a file return unless /\.pl$/; #Must end with `.pl` suffix push @file_list,$File::Find::name; },$directory ); # At this point,@file_list contains all of the files I found.
这完全相同:
my @file_list; find ( \&wanted,$directory ); sub wanted { return unless -f; return unless /\.pl$/; push @file_list,$File::Find::name; } # At this point,@file_list contains all of the files I found.
衬里看起来更好看.并且,它将我的代码保持在一起.另外,我的非本地数组变量看起来并不那么怪异.
我也喜欢以这种特殊的方式利用更短的语法.通常,我不喜欢使用推断的$_,但在这种情况下,它使代码更容易阅读.我原来的通缉与此相同:
sub wanted { my $file_name = $_; if ( -f $file_name and $file_name =~ /\.pl$/ ) { push @file_list,$File::Find::name; } }
File :: Find并不是那么棘手.你只需要记住:
>当您找到不需要的文件时,使用return转到下一个文件.
> $_包含没有目录的文件名,您可以使用它来测试文件.
>文件的全名是$File :: Find :: name.
>文件的目录是$File :: Find :: dir.