与perl的STDOUT问题

时间:2014-12-15 16:19:26

标签: xml windows perl stdout

我写了一小段代码,以便使用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完美地工作,所以这很奇怪

提前致谢

1 个答案:

答案 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);

这将为运行程序的系统创建一个具有合适目录分隔符的路径。