我已经检查了可能已经有答案的问题,但没有一个问题有帮助。
这是我的Unix编程学期项目。我创建了一个脚本,用于将HTML文件与网站中的其他文件进行比较。
该脚本完美按预期工作,直到我尝试实现第二个网站,因此我删除了第二个网站的添加代码,现在我收到了错误
Global symbol "@master" requires explicit package name
Global symbol "@child" requires explicit package name
在csite_md5
子程序中。我已多次浏览代码,无法看到问题。
我正在寻找另一组眼睛,看看我是否只是缺少一些简单的东西,通常就是这种情况。
我也是Perl的新手,因为这是我第一次使用这种语言。
#!/usr/bin/perl
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
use File::Basename;
# Path to the c-site download root directory
my $csite_dir = '/root/websites/c-site/wget/';
opendir my $dh, $csite_dir or die $!;
# Finds the sub directories c-site_'date +%F' where the c-site download is located
my @wget_subdir_csite = sort grep /^[^.]/, readdir $dh;
# Creates the absolute path to the c-site download
my $csite_master_dir = "$csite_dir$wget_subdir_csite[0]/dayzunderground.webs.com";
my $csite_child_dir = "$csite_dir$wget_subdir_csite[1]/dayzunderground.webs.com";
# Call to subroutine to append the .html file name to the absolute path
my @master_csite = &gethtml_master_csite($csite_master_dir);
my @child_csite = &gethtml_child_csite($csite_child_dir);
&csite_md5(\@master_csite, \@child_csite);
sub gethtml_master_csite{
my ($master_path) = @_;
opendir (DIR, $master_path) or die $!;
# Ends with .html and is a file
my @html_master = sort grep {m/\.html$/i && -f "$master_path/$_"} readdir(DIR);
my @files_master = ("$master_path/$html_master[0]","$master_path/$html_master[1]","$master_path/$html_master[2]","$master_path/$html_master[3]");
return @files_master
}
sub gethtml_child_csite{
my ($child_path) = @_;
opendir (DIR, $child_path) or die $!;
# Ends with .html and is a file
my @html_child = sort grep {m/\.html$/i && -f "$child_path/$_"} readdir(DIR);
my @files_child = ("$child_path/$html_child[0]","$child_path/$html_child[1]","$child_path/$html_child[2]","$child_path/$html_child[3]");
return @files_child
}
sub csite_md5{
my ($master, $child) = @_;
if(&md5sum($master[0]) ne &md5sum($child[0])){
my $filename = basename($master[0]);
system("diff -u -d -t --width=100 $master[0] $child[0] > ~/websites/c-site/diff/c-site-$filename-`date +%F`");
#print "1"
}
if(&md5sum($master[1]) ne &md5sum($child[1])){
my $filename2 = basename($master[1]);
system("diff -u -d -t --width=100 $master[1] $child[1] > ~/websites/c-site/diff/c-site-$filename2-`date +%F`");
#print "2"
}
if(&md5sum($master[2]) ne &md5sum($child[2])){
my $filename3 = basename($master[2]);
system("diff -u -d -t --width=100 $master[2] $child[2] > ~/websites/c-site/diff/c-site-$filename3-`date +%F`");
#print "3"
}
if(&md5sum($master[3]) ne &md5sum($child[3])){
my $filename4 = basename($master[3]);
system("diff -u -d -t --width=100 $master[3] $child[3] > ~/websites/c-site/diff/c-site-$filename4-`date +%F`");
#print "4"
}
}
sub md5sum{
my $file = shift;
my $digest = "";
eval{
open(FILE, $file) or die "Can't find file $file\n";
my $ctx = Digest::MD5->new;
$ctx->addfile(*FILE);
$digest = $ctx->hexdigest;
close(FILE);
};
if($@){
print $@;
return "";
}
return $digest
}
答案 0 :(得分:4)
$master
和$child
是数组引用;像$master->[0]
一样使用它们。 $master[0]
使用数组@master
,这是一个完全独立的变量。
答案 1 :(得分:1)
我认为通过您的计划并指出一些不太理想的做法可能有所帮助
调用Perl子例程时,不应使用&符号&
。这是Perl 4所要求的,它在大约22年前被取代
最好使用File::Spec
模块来处理文件路径,以处理多路径分隔符和可移植性等情况。 File::Spec
也将执行File::BaseName
不必使用shell来创建日期字符串。使用Time::Piece
模块,localtime->ymd
生成与date +%F
相同的字符串
在适当情况下使用map
而不是编写多个相同的作业更整洁,更简洁
gethtml_master_csite
和gethtml_child_csite
子例程是相同的,只是它们在内部使用不同的变量名。它们可以由单个gethtml_csite
子例程
您应该使用 lexical 文件和目录句柄,就像使用第一个opendir
一样。您还应该使用open
的三参数形式(以打开模式作为第二个参数)
如果open
失败,那么您应该在$!
字符串中包含变量die
,以便您知道 失败的原因。此外,如果您使用换行符结束字符串,则Perl不会在打印时将源文件和行号附加到字符串
如您所读,csite_md5
尝试使用不存在的数组@master
和@child
。您有数组引用 $master
和$child
。此外,子程序适用于循环结构,而不是明确地编写四个比较
md5sum
在eval
调用失败时,您使用了die
来抓住open
。明确地检查这个
从子例程返回 false 值的标准方法是裸return
。如果您return ''
,那么它将在列表上下文中评估为 true
有了这些chnages,你的代码就像这样。请问您是否有任何问题需要了解它。请注意,我无法测试它,但它确实编译了
#!/usr/bin/perl
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
use File::Spec::Functions qw/ catdir catfile splitpath /;
use Time::Piece 'localtime';
my $csite_dir = '/root/websites/c-site/wget/';
opendir my $dh, $csite_dir or die qq{Unable to open "$csite_dir": $!};
my @wget_subdir_csite = sort grep /^[^.]/, readdir $dh;
my ($csite_master_dir, $csite_child_dir) = map
catdir($csite_dir, $_, 'dayzunderground.webs.com'),
@wget_subdir_csite[0,1];
my @master_csite = gethtml_csite($csite_master_dir);
my @child_csite = gethtml_csite($csite_child_dir);
csite_md5(\@master_csite, \@child_csite);
sub gethtml_csite {
my ($path) = @_;
opendir my $dh, $path or die qq{Unable to open "$path": $!};
my @files = sort grep { /\.html$/i and -f } map catfile($path, $_), readdir $dh;
return @files;
}
sub csite_md5 {
my ($master_list, $child_list) = @_;
for my $i ( 0 .. $#$master_list ) {
my ($master, $child) = ($master_list->[$i], $child_list->[$i]);
if ( md5sum($master) ne md5sum($child) ) {
my $filename = (splitpath($master))[-1]; # Returns (volume, path, file)
my $date = localtime->ymd;
system("diff -u -d -t --width=100 $master $child > ~/websites/c-site/diff/c-site-$filename-$date");
}
}
}
sub md5sum {
my ($file) = @_;
my $digest = "";
open my $fh, '<', $file or do {
warn qq{Can't open file "$file": $!}; # '
return;
};
my $ctx = Digest::MD5->new;
$ctx->addfile($fh);
return $ctx->hexdigest;
}