perl - Perl - 无法打开和读取文件
问题描述
在给定的输入文件夹之后,我创建了一个用于验证 xml 文件的脚本。它应该从输入目录中 grep xml 文件,然后整理 xml 文件并检查条件。但它会抛出一个命令not Open at line , <STDIN> line 1
。
但它会创建一个空的日志文件。
由于我在排序时遇到numeric
错误,请对此发表评论。
所以我需要给定输入位置,脚本应该检查 xml 文件并在提到的日志文件中抛出错误。
任何人都可以帮助这个?
脚本
#!/usr/bin/perl
# use strict;
use warnings;
use Cwd;
use File::Basename;
use File::Path;
use File::Copy;
use File::Find;
print "Enter the path: ";
my $filepath = <STDIN>;
chomp $filepath;
die "\n\tpleas give input folder \n" if(!defined $filepath or !-d $filepath);
my $Toolpath = dirname($0);
my $base = basename($filepath);
my $base_path = dirname($filepath);
my ($xmlF, @xmlF);
my @errors=();
my @warnings=();
my @checkings=();
my $ecount=0;
my $wcount=0;
my $ccount=0;
my ($x, $y);
my $z="0";
opendir(DIR,"$filepath");
my @xmlFiles = grep{/\.xml$/} readdir(DIR);
closedir(DIR);
my $logfile = "$base_path\\$base"."_Err.log";
# @xmlF=sort{$a <=> $b}@xmlFiles;
@xmlF=sort{$a cmp $b}@xmlFiles;
open(OUT, ">$logfile") || die ("\nLog file couldnt write $logfile :$!");
my $line;
my $flcnt = scalar (@xmlF);
for ($x=0; $x < $flcnt; $x++)
{
open IN, "$xmlF[$x]" or die "not Open";
print OUT "\n".$xmlF[$x]."\n==================\n";
print "\nProcessing File $xmlF[$x] .....\n";
local $/;
while ($line=<IN>)
{
while ($line=~m#(<res(?: [^>]+)? type="weblink"[^>]*>)((?:(?!</res>).)*)</res>#igs)
{
my $tmp1 = $1; my $tmp2 = $&; my $pre1 = $`;
if($tmp1 =~ m{ subgroup="Weblink"}i){
my $pre = $pre1.$`;
if($tmp2 !~ m{<tooltip><\!\[CDATA\[Weblink\]\]><\/tooltip>}ms){
my $pre = $pre1.$`;
push(@errors,lineno($pre),"\t<tooltip><\!\[CDATA\[Weblink\]\]></tooltip> is missing\n");
}
}
}
foreach my $warnings(@warnings)
{
$wcount = $wcount+1;
}
foreach my $checkings(@checkings)
{
$ccount = $ccount+1;
}
foreach my $errors(@errors)
{
$ecount = $ecount+1;
}
my $count_err = $ecount/2;
print OUT "".$count_err." Error(s) Found:-\n------------------------\n ";
print OUT "@errors\n";
$ecount = 0;
my $count_war = $wcount/2;
print OUT "$count_war Warning(s) Found:-\n-------------------------\n ";
print OUT "@warnings\n";
$wcount = 0;
my $count_check = $ccount/2;
print OUT "$count_check Checking(s) Found:-\n-------------------------\n ";
print OUT "@checkings\n";
$wcount = 0;
undef @errors;
undef @warnings;
undef @checkings;
close IN;
}
}
解决方案
readdir
返回裸文件名,不带路径。
因此,当您继续打开这些文件时,您需要在返回的名称前面加上从中读取它们readdir
的目录名称,here 。或立即构建完整路径名readdir
$filepath
use warnings;
use strict;
use feature 'say';
use File::Spec;
print "Enter the path: ";
my $filepath = <STDIN>;
chomp $filepath;
die "\nPlease give input folder\n" if !defined $filepath or !-d $filepath;
opendir(my $fh_dir, $filepath) or die "Can't opendir $filepath: $!";
my @xml_files =
map { File::Spec->catfile($filepath, $_) }
grep { /\.xml$/ }
readdir $fh_dir;
closedir $fh_dir;
say for @xml_files;
我使用File::Spec将文件名可移植地拼凑在一起。
map
也可以做到这grep
一点,以便只对文件列表进行一次传递
my @xml_files =
map { /\.xml$/ ? File::Spec->catfile($filepath, $_) : () }
readdir $fh_dir;
空列表()
在返回的列表中变平,实际上完全消失了。
以下是对代码的一些注释。请注意,这通常在Code Review中完成,但我觉得这里需要它。
首先:预先声明一长串变量。事实上,在尽可能小的范围内声明是很重要的。事实证明,这些变量中的大多数确实可以在使用它们的地方声明,如下面的评论所示。
最好使用以下方法找到可执行文件的位置
use FindBin qw($RealBin);
where
$RealBin
也解析链接(相对于$Bin
, 也可用)在声明时分配
()
给数组不会做任何事情;它与正常情况完全相同my @errors;
。他们也可以一起去,my (@errors, @warnings, @checks);
。如果数组有东西然后= ()
清除它,什么是清空数组的好方法分配 a
"0"
使变量成为字符串。虽然 Perl 通常会根据需要在字符串和数字之间进行转换,但如果需要数字,则使用数字,my $z = 0;
词法文件句柄 (
open my $fh, ...
) 优于 glob (open FH, ...
)我不明白排序中关于“数字错误”的评论。
cmp
运算符按字典顺序排序,用于数字排序<=>
当在标量上下文中使用数组时——例如,当分配给一个标量时——返回元素的数量。所以不需要
scalar
但做my flcnt = @xmlF;
对于数组索引的迭代,使用
$#ary
的最后一个元素的索引@ary
,对于foreach my $i (0..$#xmlF) { ... }
但是如果没有使用索引(我没有看到任何),那么循环遍历元素
foreach my $file (@xmlF) { ... }
当您检查文件时
open
打印错误 $! ,open ... or die "... : $!";
. 这是在代码的其他地方完成的,并且应该总是这样做。local $/;
取消设置输入记录分隔符,是什么使以下读取占用整个文件。如果这是有意的,那么$line
这不是一个好名字。另请注意,可以在条件内声明变量,while (my $line = <$fh>) { }
我无法评论正则表达式,因为我不知道它应该完成什么,但它很复杂;有没有机会简化这一切?
这一系列
foreach
循环只计算出这些数组的元素数量;那么就不需要循环了,只是my $ecount = @errors;
(等)。这也允许您将这些计数器变量的声明保持在最小范围内。undef @errors;
不需要 (etc),因为这些数组对每个文件都计数,因此您可以在循环中声明它们,在每次迭代时(并且在最小范围内)重新声明它们。当你想清空一个数组时,做@ary = ();
比做要好undef
;这样它就不会在下次使用时重新分配
推荐阅读
- java - 是什么导致 grails 应用程序在某些部署中创建更多线程
- python - 我正在设置 python 类,但它打印
我正在设置 python 类,但它在 0x03391d90 处打印 < main .deteil 对象
我试图在谷歌搜索,但没有帮助我
Python 类
class person: def __init__(self,fn
- javascript - Adding custom function to object prototype
- python - Python 装饰器来安排函数的执行
- reactjs - 在状态切换某些数据时,对存储的更新导致其他一些数据丢失
- javascript - 承诺 {
api 调用通过从客户端到服务器的节点代理完成时的问题 - excel - My Userform keep shrinking after every use
- java - 在 E4 上保存和恢复工作台
- java - In spring batch, how to insert a piece of code just after reading a list of item by bulk, with given list of item as parameter?
- python - dask.linalg.solve(A, b) 上的 MemoryError 用于求解 Ax = b