如何在Perl中打开一个文件的数组? [英] How do I open an array of files in Perl?

查看:151
本文介绍了如何在Perl中打开一个文件的数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Perl中,我从一个目录中读取文件,并且我想同时打开它们(但是一行一行地打开),这样我就可以执行一个使用所有第n行(如串联)的函数。

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆