如何在Perl中打开一个文件的数组? [英] How do I open an array of files in Perl?
问题描述
my $ text =`ls | grep.txt;
我的@temps = split(/ \ n /,$ text);
my @files;
为我的$我(0 .. $#临时工){
我的$文件;
open($ file,<,$ temps [$ i]);
push(@ files,$ file);
}
my $ concat;
for my $ i(0 .. $#files){
my @blah =< $ files [$ i]>;
$ concat。= $ blah;
}
print $ concat;
我只是一堆错误,使用未初始化的值和GLOB(..)错误。那么我怎样才能做到这一点呢? 解决方案
很多问题。首先调用ls | grep:)
让我们从一些代码开始:
首先,获取文件列表:
my @files = glob('* .txt');
但是,最好测试给定的名字是否与文件或目录相关:
my @files = grep {-f} glob('* .txt');
现在,我们打开这些文件来阅读它们:
my @fhs = map {open my $ fh,'<',$ _; $ fh} @files;
但是,我们需要一种处理错误的方法 - 在我看来,最好的方法是添加: / p>
use autodie;
在脚本的开头(安装autodie,如果还没有的话)。您也可以:
使用致命的qw(打开);
现在,我们已经得到了第一行(如您在示例中所示)所有的输入,并连接它:
my $ concatenated ='';
for my $ fh(@fhs){
my $ line =< $ fh>;
$串联。= $ line;
$ b 这是完美的,可读的,但仍然可以缩短,同时保持(在我看来)的可读性为:
pre $ my $ concatenated = join'',map {scalar< $ _> } @fhs;
效果是一样的 - $ concatenated包含所有文件的第一行
所以,整个程序看起来像这样:
$ p $ #!/ usr / bin / perl
使用严格;
使用警告;
使用autodie;
#使用致命的qw(打开); #取消注释,如果你没有autodie
my @files = grep {-f} glob('* .txt');
my @fhs = map {open my $ fh,'<',$ _; $ fh} @files;
my $ concatenated = join'',map {scalar <$ _> } @fhs;
现在,您可能希望连接第一行,而不是所有行。在这种情况下,你需要像下面这样的代码: $ concatenated = ...
代码
my $ concatenated ='';
while(my $ fh = shift @fhs){
my $ line =< $ fh>;
if(defined $ line){
push @fhs,$ fh;
$串联。= $ line;
} else {
close $ fh;
}
}
In perl, I read in files from a directory, and I want to open them all simultaneously (but line by line) so that I can perform a function that uses all of their nth lines together (e.g. concatenation).
my $text = `ls | grep ".txt"`;
my @temps = split(/\n/,$text);
my @files;
for my $i (0..$#temps) {
my $file;
open($file,"<",$temps[$i]);
push(@files,$file);
}
my $concat;
for my $i (0..$#files) {
my @blah = <$files[$i]>;
$concat.=$blah;
}
print $concat;
I just a bunch of errors, use of uninitialized value, and GLOB(..) errors. So how can I make this work?
A lot of issues. Starting with call to "ls | grep" :)
Let's start with some code:
First, let's get list of files:
my @files = glob( '*.txt' );
But it would be better to test if the given name relates to file or directory:
my @files = grep { -f } glob( '*.txt' );
Now, let's open these files to read them:
my @fhs = map { open my $fh, '<', $_; $fh } @files;
But, we need a way to handle errors - in my opinion the best way is to add:
use autodie;
At the beginning of script (and installation of autodie, if you don't have it yet). Alternatively you can:
use Fatal qw( open );
Now, that we have it, let's get the first line (as you showed in your example) from all of the inputs, and concatenate it:
my $concatenated = '';
for my $fh ( @fhs ) {
my $line = <$fh>;
$concatenated .= $line;
}
Which is perfectly fine, and readable, but still can be shortened, while maintaining (in my opinion) readability, to:
my $concatenated = join '', map { scalar <$_> } @fhs;
Effect is the same - $concatenated contains first lines from all files.
So, whole program would look like this:
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
# use Fatal qw( open ); # uncomment if you don't have autodie
my @files = grep { -f } glob( '*.txt' );
my @fhs = map { open my $fh, '<', $_; $fh } @files;
my $concatenated = join '', map { scalar <$_> } @fhs;
Now, it might be that you want to concatenate not just first lines, but all of them. In this situation, instead of $concatenated = ...
code, you'd need something like this:
my $concatenated = '';
while (my $fh = shift @fhs) {
my $line = <$fh>;
if ( defined $line ) {
push @fhs, $fh;
$concatenated .= $line;
} else {
close $fh;
}
}
这篇关于如何在Perl中打开一个文件的数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!