简体   繁体   English

Perl的STDOUT问题

[英]STDOUT issue with perl

I wrote a little piece of code in order to process some XML files recursively on Windows using XMLLINT 我写了一些代码,以便使用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; 

This code works perfectly on Ubuntu but I'm having troubles redirecting the output of 这段代码在Ubuntu上可以正常使用,但是我在重定向输出时遇到了麻烦

C://toolslibxml//xmllint.exe --dropdtd --noent $file into a file, if I take the operartor ">" all the outputs are printed into the screen but if I put it back the file are empty, I have tried also a variation using back-quoats and a variable the result was the same C://toolslibxml//xmllint.exe --dropdtd --noent $file到文件中,如果我将操作员“>”全部输出打印到屏幕中,但是如果我放回去,则该文件为空,我也尝试了使用后代和变量的变体,结果是相同的

On prompt command the command C://toolslibxml//xmllint.exe --dropdtd --noent file > out_putfile work prefectly so it's very strange 在提示命令上,命令C://toolslibxml//xmllint.exe --dropdtd --noent file > out_putfile正常工作,因此非常奇怪

Thanks in advance 提前致谢

TL;DR: Skip to the end for my guess to the solution. TL; DR:跳到最后,以我对解决方案的猜测。

I will go through your script and comment on what you are doing. 我将检查您的脚本并评论您的工作。 There are a lot of questionable code. 有很多可疑的代码。

#!C:\Perl64\bin\perl

The shebang is ignored in Windows, but any switches are parsed. 在Windows中,shebang会被忽略,但是会解析所有开关。 You should be using use strict; use warnings; 您应该使用use strict; use warnings; use strict; use warnings; -- the problems do not go away if you don't use them, they are just hidden. -如果您不使用它们,问题就不会消失,它们只是被隐藏了。

$ENV{PATH} = 'C:\Users\NLP-Lingua\Desktop\echos';
my $racine = $ENV{PATH};
&recurse($racine);

As near as I can tell, there is no reason to involve $ENV{PATH} here at all. 据我所知,这里根本没有理由涉及$ENV{PATH} This only controls what programs the shell your Perl program is running in can access. 这仅控制运行Perl程序的Shell可以访问哪些程序。 By setting it to this folder, you are basically restricting your temporary shell from accessing programs in Windows PATH , and I doubt that is what you are trying to do. 通过将其设置到此文件夹,基本上可以限制临时外壳访问Windows PATH程序,并且我怀疑这是您要尝试的操作。

Also, you should not use & to prefix subroutines, that is old style, and it is used to override prototypes. 另外,您不应使用&前缀子程序(这是旧样式)的前缀,该子程序用于覆盖原型。 And if you don't know what that means, check perldoc perlsub , or just do as I recommend. 而且,如果您不知道这意味着什么,请检查perldoc perlsub或按照我的建议进行操作。

This whole code can simply be written: 整个代码可以简单地写成:

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");

As I said in the comments, $file\\_out is a strange way to prevent $file_out to be interpolated as a variable. 正如我在评论中所说, $file\\_out是防止$file_out插值为变量的一种奇怪方法。 You should use ${file}_out , or better yet, make a new variable: my $file_out = $file . "_out"; 您应该使用${file}_out ,或者最好使用一个新变量: my $file_out = $file . "_out"; my $file_out = $file . "_out";

open (OUT, ">$file\_translated.xml");

You never use this file handle, so you will be filling your directories with empty files. 您永远不会使用此文件句柄,因此将用空文件填充目录。 And every time you run this script, you will likely create even more empty files. 而且,每次运行此脚本时,您可能会创建更多的空文件。

                close(IN);

You never opened this file handle. 您从未打开过该文件句柄。

As for why your program is not working, I am guessing it is this line: 至于为什么您的程序无法正常工作,我猜是这行:

    my $file = $dossier."/".$file;

When you interpolate this, you get something like foo/bar.xml , and / is used by Windows cmd shell. 进行插值时,会得到类似foo/bar.xml ,并且Windows cmd shell使用/ Use backslash, or better yet, use File::Spec::catfile : 使用反斜杠,或者更好的是,使用File::Spec::catfile

use File::Spec;
my $file = File::Spec->catfile($dossier, $file);

This will create a path with suitable directory separators for the system the program is running on. 这将为程序运行所在的系统创建一个带有适当目录分隔符的路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM