我写了一小段代码,以便使用XMLLINT在Windows上递归处理一些XML文件
#!C:\Perl64\bin\perl
$ENV{PATH} = 'C:\Users\NLP-Lingua\Desktop\echos';
my $racine = $ENV{PATH};
&recurse($racine);
sub recurse {
my $dossier = shift(@_);
opendir(DOSSIER, $dossier);
my @files = readdir (DOSSIER);
#print "liste des fichier de $dossier : @files\n";
foreach my $file (@files) {
next if $file =~ /^\.\.?$/;
my $file = $dossier."/".$file;
if (-f $file) {
#print $file, "\n";
if (($file =~ /\.xml$/)) {
system("C://toolslibxml//xmllint.exe --dropdtd --noent $file > $file\_out");
open (OUT, ">$file\_translated.xml");
}
close(IN);
}
}
if (-d $file) {
&recurse($file);
}
}
close IN;
close OUT;
这段代码在Ubuntu上完美运行,但我在重定向
的输出方面遇到了麻烦 C://toolslibxml//xmllint.exe --dropdtd --noent $file
到文件中,如果我把操作符“>”所有输出都打印到屏幕上,但如果我把它放回去,文件是空的,我也尝试了使用后退和变量的变化,结果是相同的
在提示符下命令命令
C://toolslibxml//xmllint.exe --dropdtd --noent file > out_putfile
完美地工作,所以这很奇怪
提前致谢
答案 0 :(得分:1)
TL; DR:跳到最后我猜测解决方案。
我将通过你的剧本并评论你在做什么。有很多有问题的代码。
#!C:\Perl64\bin\perl
Windows中忽略了shebang,但解析了所有开关。您应该使用use strict; use warnings;
- 如果您不使用它们,问题就不会消失,它们只是隐藏起来。
$ENV{PATH} = 'C:\Users\NLP-Lingua\Desktop\echos';
my $racine = $ENV{PATH};
&recurse($racine);
尽我所知,没有理由在这里涉及$ENV{PATH}
。这仅控制运行Perl程序的shell可以访问的程序。通过将其设置为此文件夹,您基本上限制您的临时shell访问Windows PATH
中的程序,我怀疑您正在尝试做什么。
此外,您不应该使用&
为子例程添加前缀,即旧样式,并且它用于覆盖原型。如果您不知道这意味着什么,请查看perldoc perlsub
,或按照我的建议进行操作。
这整个代码可以写成:
recurse('C:\Users\NLP-Lingua\Desktop\echos');
sub recurse {
my $dossier = shift(@_);
opendir(DOSSIER, $dossier);
my @files = readdir (DOSSIER);
#print "liste des fichier de $dossier : @files\n";
foreach my $file (@files) {
next if $file =~ /^\.\.?$/;
my $file = $dossier."/".$file;
if (-f $file) {
#print $file, "\n";
if (($file =~ /\.xml$/)) {
system("C://toolslibxml//xmllint.exe --dropdtd --noent $file > $file\_out");
正如我在评论中所说,$file\_out
是一种阻止$file_out
作为变量进行插值的奇怪方法。您应该使用${file}_out
,或者更好的是,创建一个新变量:my $file_out = $file . "_out";
open (OUT, ">$file\_translated.xml");
您永远不会使用此文件句柄,因此您将使用空文件填充目录。每次运行此脚本时,您都可能会创建更多空文件。
close(IN);
您从未打开此文件句柄。
至于为什么你的程序不能正常工作,我猜它就是这一行:
my $file = $dossier."/".$file;
当您插入此内容时,您会得到类似foo/bar.xml
的内容,并且Windows cmd shell会使用/
。使用反斜杠,或者更好的是,使用File::Spec::catfile
:
use File::Spec;
my $file = File::Spec->catfile($dossier, $file);
这将为运行程序的系统创建一个具有合适目录分隔符的路径。