打开通过$ _命令行提供的文件名是否存在问题?

Geo*_*pty 4 perl file-io

我无法修改处理作为命令行参数传递的文件的脚本,仅用于复制这些文件,另外修改这些文件.以下perl脚本适用于复制文件:

use strict;
use warnings;

use File::Copy;

foreach $_ (@ARGV) {
   my $orig = $_;
   (my $copy = $orig) =~ s/\.js$/_extjs4\.js/;
   copy($orig, $copy) or die(qq{failed to copy $orig -> $copy});
}
Run Code Online (Sandbox Code Playgroud)

现在我有了名为"*_extjs4.js"的文件,我想将它们传递给一个脚本,该脚本同样从命令行获取文件名,并进一步处理这些文件中的行.到目前为止,我能够成功获得文件句柄,如下面的脚本,它的输出显示:

use strict;
use warnings;

foreach $_ (@ARGV) {
    print "$_\n";
    open(my $fh, "+>", $_) or die $!;
    print $fh;
    #while (my $line = <$fh>) {
    #    print $line;
    #}
    close $fh;
}
Run Code Online (Sandbox Code Playgroud)

哪些产出(部分):

./filetree_extjs4.js
GLOB(0x1a457de8)
./async_submit_extjs4.js
GLOB(0x1a457de8)
Run Code Online (Sandbox Code Playgroud)

我真正想做的是,而不是打印文件句柄的表示,是使用文件本身的内容. 一个开始是打印文件行,我试图用上面注释掉的代码.

但是该代码没有效果,文件的行不会打印出来.我究竟做错了什么?$ _用于处理命令行参数和用于处理文件内容的参数之间是否存在冲突?

Zai*_*aid 6

看起来这里有几个问题.


我真正想做的是,而不是打印文件句柄的表示,是使用文件本身的内容.

print $fh返回的原因GLOB(0x1a457de8)是因为标量$fh是文件句柄而不是文件本身的内容.要访问文件本身的内容,请使用<$fh>.例如:

while (my $line = <$fh>) {
    print $line;
}

# or simply print while <$fh>;
Run Code Online (Sandbox Code Playgroud)

将打印整个文件的内容.

这记录在pelrdoc perlop:

如果尖括号包含的是一个简单的标量变量(例如 <$foo>),那么该变量包含要从中输入的文件句柄的名称,或者其typeglob,或者对它的引用.


但它已经尝试过了!

我知道.将打开模式更改为后尝试使用+<.

根据perldoc perlfaq5:

为什么我打开一个文件读写它会把它擦掉?

因为你正在使用这样的东西,它截断文件然后给你读写访问:

  open my $fh, '+>', '/path/name'; # WRONG (almost always)
Run Code Online (Sandbox Code Playgroud)

哎呦.你应该使用它,如果文件不存在将失败:

  open my $fh, '+<', '/path/name'; # open for update
Run Code Online (Sandbox Code Playgroud)

">"永远使用clobbers或创造.使用"<"永远不会.这 "+"并没有改变这一点.

不言而喻的是,or die $!之后的open强烈建议.


但退后一步.

有一种更多的Perlish方式来备份原始文件并随后对其进行操作.事实上,它可以通过命令行本身(!)使用-i标志:

$ perl -p -i._extjs4 -e 's/foo/bar/g' *.js
Run Code Online (Sandbox Code Playgroud)

有关perldoc perlrun详细信息,请参阅


我不能满足我的需求到命令行.

如果操作对于命令行来说太多了,那么该Tie::File模块值得一试.