2009-06-09 4 views
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; 
+1

この課題はありますか? –

+1

私も同じことを考えていましたが、導入テキストのサンプルの問題と同じように簡単に問題になる可能性があります。 – inkedmn

+1

ある時点で、「別のファイル」を開いてそのファイルに書き込む必要があります。また、その形式の「公開」を使用しないようにしてください。通常の$変数で使用するためにファイルハンドルを返すフォームを使用します:open($ fh、 "filename");または変形の1つ。 –

答えて

4

を、のは、一つ一つを手放す:ラインをシェバング

#!/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 $count = 0; 
my $string = ''; 

最小限の可能な範囲内の変数を宣言して(必要に応じて)初期化します(必要な場合)。

my $count; 

変数$stringは、コード内の他の場所では使用されません。

foreach $_(@body){ 

これは愚かです。ループ変数が指定されていない場合、forは$ _を使用します。字句ループ変数を指定すると、そのままの状態に保つ方が簡単です。

for my $line (@body) { 

しかし、私はあなたがファイルを嫌うとは思わない。ラインだからX.が含まれている場合は成功した試合になり

 if ($_ =~ m/[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__ 

UPDATE:使用すると、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>; 
+0

私はすべてのあなたのレビューの発言に同意します。しかし、問題のポイント3は「ファイル全体の「X」文字の数を数える」と尋ねる。代わりに、あなたのソリューションは、「X」文字を含む単語(文字列の定義に依存する文字列)の数を数えます。 – user55400

+0

@blixtor:それをキャッチしていただきありがとうございます。もちろん、各単語には複数のX文字を含めることができます。実際には、私は今OPが行を単語に分割することに気にしないことを理解しています。 –

+0

3つの引数を取る形式のopenは時には有用であり、時にはそうではありません。 2-argオープンを安全に使用するのは簡単ですが、openプラグマまたは-CスイッチからデフォルトのIOレイヤーを取得する機能が必要な場合もあります。あなたが2-argが開くことを批判するつもりならば、少なくとも "それは新しい方法です"というだけではなく、いつかは可変ファイル名を安全に使用できないと言うでしょう。 – ysth

1

if節の両方の枝に$_を印刷しています。 elseブランチを取り除く。あなたの質問で「文字列」を仮定し

+0

新人には「印刷する」ことは明らかではないかもしれません。 '$ _'が表示されますが、それが起こります。 –

+0

。私はもう少し冗長であったかもしれない。ごめんなさい。 – innaM

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; 
関連する問題