[英]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.