ファイルを読み取った後、ファイル内の特定の文字を出力するにはどうすればよいですか?
-
13-09-2019 - |
質問
Perlスクリプトを使用してファイルを読んでいます。このファイルはさまざまな文字を含む文字列で構成されており、文字「X」を含む文字列を識別することになっています。どうすればいいのか知りたいです (1) この文字列を出力します (「X」を含む) および (2) この文字列を別のファイルに書き込みます (3) ファイル全体の「X」文字の数を数えます. 。以下のスクリプトは、ファイル全体を再度出力します。助言がありますか?
#!/use/bin/perl
use strict;
use warnings;
open (FILE, "/home/user/Desktop/infile.phy") || die "cant open file\n";
my @body = <FILE>;
close (FILE);
my $count= 0;
my $string = '';
foreach $_(@body){
if ($_ =~ m/[X]/){
print "$_";
$count++;
print $count;
}
else {
print ;
}
}
exit;
解決
これはコードレビューなので、一つずつ見ていきましょう。
#!/use/bin/perl
そのシバン行はおそらくタイプミスです。おそらくそうあるべきです
#!/usr/bin/perl
または何でも which perl
システムに戻ります。
use strict;
use warnings;
良い。
open (FILE, "/home/user/Desktop/infile.phy") || die "cant open file\n";
レキシカル ファイルハンドルを使用できる場合、パッケージ グローバル ファイルハンドルは必要ありません。3 引数形式の open
最近では好ましいです。また、エラー メッセージには、開けなかったファイルが示されているはずです。
my $filename = '/home/user/Desktop/infile.phy';
open my $input, '<', $filename
or die "Cannot open '$filename' for reading: $!";
my @body = <FILE>;
ファイルを配列に読み込んでいます。この場合、それはまったく必要ありません。
my $count = 0;
my $string = '';
可能な限り最小のスコープで変数を宣言し、(必要に応じて) 初期化します。
my $count;
変数 $string
コード内の他の場所では使用されていません。
foreach $_(@body){
これはばかげています。 for
ループ変数が指定されていない場合は $_ を使用します。代わりに字句ループ変数を指定すると、処理をわかりやすくすることができます。
for my $line ( @body ) {
ただし、ファイルを丸呑みする必要はないと思います。
if ($_ =~ m/[X]/){
行に X が含まれている場合、一致は成功します。したがって、それは次と同等です /X/
. 。ただし、これでは「X」を含む単語はわかりません。そのためには、単語が何であるかを判断し、単語レベルでマッチングを行う必要があります。
以上のことを念頭に置いて、次のスクリプトを検討してください。私が考える単語について単純化した仮定を立てました。これを基にしてすべての要件を満たすことができるはずです。
#!/usr/bin/perl
use strict;
use warnings;
my $filename = "$ENV{TEMP}/test.txt";
open my $input, '<', $filename
or die "Cannot open '$filename' for reading: $!";
my $count;
while ( my $line = <$input> ) {
my @words = grep { /X/ } split /\b/, $line;
$count += @words;
print join(', ', @words), "\n";
}
print "$count\n";
__END__
アップデート: 各行内で 1 つ以上の X 文字を含む単語を検索する必要がない場合、while ループは簡略化されます。
while ( <$input> ) {
$count += (my @matches = /(X)/g );
print if @matches;
}
$_ を使用して。ただし、これはおそらく非効率的です (一致した X 文字をそれぞれ保存していることを考えると)。この場合、 tr
最もよく機能します:
my ($count, $n);
$n = tr/X// and $count += $n and print while <$input>;
他のヒント
印刷中です $_
if 節の両方の分岐にあります。else ブランチを削除します。
質問の「文字列」が「行」と等しいと仮定します。
use strict;
use warnings;
@ARGV=qw(/home/user/Desktop/infile.phy);
my $count = 0;
open my $outfile, '>', 'outfile' or die $!;
while (<>) {
my $cnt = tr/X/X/;
if ($cnt) {
print;
print $outfile $_;
}
$count += $cnt;
}
close $outfile or die $!;
print $count;