多くの問題。「ls | grep」の呼び出しから始めます:)
いくつかのコードから始めましょう:
まず、ファイルのリストを取得しましょう。
my @files = glob( '*.txt' );
ただし、指定された名前がファイルまたはディレクトリに関連しているかどうかをテストすることをお勧めします。
my @files = grep { -f } glob( '*.txt' );
それでは、これらのファイルを開いて読み取りましょう。
my @fhs = map { open my $fh, '<', $_; $fh } @files;
しかし、エラーを処理する方法が必要です。私の意見では、以下を追加するのが最善の方法です。
use autodie;
スクリプトの開始時 (およびまだ持っていない場合は autodie のインストール時)。または、次のことができます。
use Fatal qw( open );
これで、すべての入力から最初の行 (例で示したように) を取得し、それを連結しましょう。
my $concatenated = '';
for my $fh ( @fhs ) {
my $line = <$fh>;
$concatenated .= $line;
}
これは完全に問題なく、読みやすいですが、(私の意見では)読みやすさを維持しながら、次のように短縮できます。
my $concatenated = join '', map { scalar <$_> } @fhs;
効果は同じです - $concatenated にはすべてのファイルの最初の行が含まれます。
したがって、プログラム全体は次のようになります。
#!/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;
ここで、最初の行だけでなく、それらすべてを連結したい場合があります。この状況では、$concatenated = ...
コードの代わりに、次のようなものが必要になります。
my $concatenated = '';
while (my $fh = shift @fhs) {
my $line = <$fh>;
if ( defined $line ) {
push @fhs, $fh;
$concatenated .= $line;
} else {
close $fh;
}
}