0

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;
4

3 に答える 3

4

これはコード レビューなので、1 つずつ見ていきましょう。

#!/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>;
于 2009-06-09T13:36:49.360 に答える
1

$_if節の両方のブランチで印刷しています。else ブランチを削除します。

于 2009-06-09T13:21:52.540 に答える
0

質問の「文字列」が「行」に等しいと仮定します。

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;
于 2009-06-09T13:29:58.920 に答える