• 締切済み

文字列をカウントする方法

ファイルを読み込んで、その中の特定の文字列たとえば"映画"が何個あるかを調べるプログラムを作っているのですが、動作しません。ファイルには、改行やタブが入っているのですが、問題はファイルの読み込み方なのか、カウンタの方なのか分かりません。次がプログラムですので何か分かる方は教えてください。 if (open(FH, "data/log.txt")) { @file = <FH>; close(FH); } while(<STDIN>){ $movie=0; if(@file == "映画" ){ $movie++; } print $movie; }

  • Perl
  • 回答数3
  • ありがとう数3

みんなの回答

回答No.3

箇数が知りたいだけなら全てを @file に入れる必要はありません。(後で内容を別のことに使う場合は別ですが)。 で、行の中に「映画」が何個含まれているかは $count = 0; $count++ while(/映画/g); で出せます。(これは $_ に対して比較しているので $_ =~ /映画/g と同じです)。 ファイル全体ということならばこんな感じでしょう。 open(F, '< ファイル名') or die; $count = 0; while (<F>) {  $count++ while (/映画/g); } close(F); 但し行末に「映」があって次の行頭に「画」がある場合はこれでは数えられません。そういうのもカウントしたい場合はやはり全部読んだ方が簡単です。読むとメモリが足りなくなるぐらい大きいファイルの場合は行末の1文字が「映」の場合にそれを記録しておき、次の行を読んだ時に先頭が「画」かどうかを調べるということをすればできます。

iwaigawa2006
質問者

お礼

ご回答ありがとうございます。大変参考になりました。試してみたいと思います。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

こんな感じでイイと思います。 if (open(FH, "data/log.txt")) { local $/ = undef; $file = <FH>; close(FH); } $movie=($file=~s/映画/映画/g);#trはうまくない print $movie;

iwaigawa2006
質問者

お礼

ご回答ありがとうございます。早速ためさせていただきます。

回答No.1

問題なのはカウンタ部分です。 プログラムの一文一文がどういう動作をするのか、しっかり理解しましょう。 if (open(FH, "data/log.txt")) { @file = <FH>; close(FH); } ここまでで、読み込んだファイル(data/log.txt)の内容は@fileという配列に読み込まれています。 あとは、foreachループを使って@fileの中から1行ずつ取り出し、それぞれに"映画"の文字がいくつ入っているかを数えます。 文字列の中に"映画"の文字がいくつ入っているかは、 $count = ($line =~ tr/映画/映画/); と書くと、$countに$line中にある"映画"の文字の数が入ります。 あと、$movieの初期化はループの外でしないといけません。 これだけのヒントでプログラムが組めます。あとは自力で頑張ってみてください。

iwaigawa2006
質問者

お礼

間違って、お礼より先に補足のほうに書いてしまいましたが、ご回答のお礼申し上げます。

iwaigawa2006
質問者

補足

次のように作ってみましたが、実際に起動してみるとエラーになります。まだどこかおかしいでしょうか? #!/usr/local/bin/perl if (open(FH, "data/block.txt")) { @file = <FH>; close(FH); } foreach $count (@file){ $count = ($line =~ tr/映画/映画/); } print $count; exit;

関連するQ&A

  • 文字列をカウントするにはどうすればいいのでしょうか?

    ファイル読み込み後その中の特定の文字列、「映画」の個数をカウントするというプログラムを次のように作ってみましたが、実際に起動してみるとエラーになります。何かわかる方がいれば教えてください。 #!/usr/local/bin/perl if (open(FH, "data/log.txt")) { @file = <FH>; close(FH); } foreach $count (@file){ $count = ($line =~ tr/映画/映画/); } print $count; exit;

    • ベストアンサー
    • CGI
  • ファイルから読み込んだ文字を

    ファイルから読み込んだ全角文字をあるキーワード(例えば"田中")が含んでいるか否かを判定するプログラムをつくりたいのですが、なかなか上手くいきません。ファイルをopenし中の文字を読込み、それを変数に格納、ifでeq使って判定したのですが、全角は判定してくれません。全角を判定するには一体どうしたら良いのでしょうか? $filename = "####.txt"; open( $fh, "< $filename" ) #ファイルopen or die "Cannot open $file: $!"; $key = 'キ'; #キーワードを決めて while ($c = getc $fh ) { #比較する if($c eq $key){ print "キーワードを見付けました。"; } } close(fh); getcだとおそらく全角は文字コードを読み込んでしまうような感じでしょうか?print $c "\n";とすると文字化けします。しかし、printf("%d", $c);だと何も表示してくれません。これはord関数を使わねばならないのでしょうか?それとも別な方法が?等などためしたのですが、もう分かりません。 御指導御鞭撻をよろしくお願いします。

  • 文字列を指定して,別のファイルでその文字列が存在する行を出力する

    いつもお世話になっております. 環境はWindows XP Pro でActiveperlを用いてプログラムをしております. この度,皆様にご意見をうかがいたいのは,「文字列を指定して,別のファイルでその文字列が存在する行を出力する」という内容です. まず,以下のテキストファイルがあります. data.txt ---------------------- A BA C DA E FA G sansyo.txt ----------------------------- B D F ------------------------------- 処理として,data.txtでsansyo.txtの行が "含まれる"行数を出力する ------------------------------- output.txt ------------------------------- 2 4 6 ここで自分なりにプログラムを組んでみました. ----------------------------------- open(FILE, "sansyo.txt"); open(FILE2,"data.txt"); @file = <FILE>; close(FILE); @file2 = <FILE2>; close(FILE2); foreach $line (@file) { foreach $line2 (@file2) { if ($line =~ $line2){ $hit = $.; } open(NEWFILE, " >> output.txt") or die "$!"; print NEWFILE $hit; close(NEWFILE); } } #ここまで ------------------------------------- ですが,永久ループに入ってしまったようにファイルはできるのですが, 出力されてきません. 間違っている点をご指摘ください.

    • ベストアンサー
    • Perl
  • perlプログラム

    (1)のプログラムではtest.txtの内容を表示することができました。 (2)ではaaaが表示されつづけると思いますが、何も表示されません。 なにかまちがっていると思いますが、わかりません。 よろしくお願いします。 --------------------------------------------------------------------------------- (1) --------------------------------------------------------------------------------- sub Main() { LAST:while(){ if(defined(open(FILE,"test.txt"))){ flock(FILE,1); while(<FILE>){ print $_; last LAST if($_ == 0); } } sleep(1); } close(FILE); } &Main(); ------------------------------------------------------------------------------- (2) ------------------------------------------------------------------------------- sub Main() { LAST:while(){ if(defined(open(FILE,"test.txt"))){ flock(FILE,1); while(<FILE>){ print "aaa";  ←変更箇所 last LAST if($_ == 0); } } sleep(1); } close(FILE); } &Main(); -------------------------------------------------------------------------------

  • ログファイルを削除するcgiプログラム

    ログファイルを削除するcgiプログラム -------------------- $GYOUSUU = $FORM{'GYOUSUU'}; #--- ログファイルオープン open(FH,"***.log"); flock(FH,2); @FILES = <FH>; flock(FH,8); close FH; undef $FILES[$GYOUSUU]; open (FH2,">***.log"); @filew = "@FILES\n"; print FH2@filew; close(FH2); -------------------- となっているのですが、修正後にログファイルの行の頭に、半角スペースが入ってしまいます。 どこを修正すればいいのでしょうか?

    • ベストアンサー
    • Perl
  • 文字列の抽出

    指定したファイルの中から'<'と'>'とで囲まれた部分文字列を抽出したいのですが方法がわかりません。どのようにしたらできるでしょうか? *ファイルは制御コードが混じっているのでバイナリとして扱わないといけないかもしれません。 よろしくお願い致します。 ------------------------------------------------- open(IN, "test.dat"); open(OUT, "> out.txt"); binmode(IN); while (<IN>) { /^<(\w+)>$/; print OUT "$1\n"; } close(IN); close(OUT);

    • ベストアンサー
    • Perl
  • 範囲演算子と文字列マッチングを組み合わせたときの解除方法

    Windows-XP上でActivePerl/5.8.8を利用しています。 テキストファイルなどで、ある文字列が現れた行から、ある文字列が現れるまで、 ということを判定させるときに、範囲演算子が使えるということを知りました。 while(<>){     chomp;     if(/^START$/ .. /^END$/){ # 範囲指定         ・・・         STARTの行から、ENDの行までこのブロックに入る     } } 1ファイルに対してだけ処理させるときは上手く行くのですが、 連続して複数のファイルを処理させようとすると、 2番目のファイルからは、開始条件(/^START$/)が既に成立したと 判断されてしまうようで、該当行が現れていないのに、ifブロックに 入ってしまいます。 foreach(@ARGV){ # 複数ファイルに対して処理させる     open(FH,$_) || die;     while(<FH>){        chomp;        if(/^START$/ .. /^END$/){ # 範囲指定            ・・・            1つ目のファイルではSTARTの行から、ENDの行まででこのブロックに入るが、            2つ目のファイルではSTARTの行が現れないうちからこのブロックに入ってしまう。        }     } close(FH); } これを2つ目のファイル以降も、範囲指定の開始条件が成立していない 状態から処理させるためには、どのようにすれば良いでしょうか。 よろしくお願い致します。

    • ベストアンサー
    • Perl
  • ファイル内の文字列を置換するcscriptについて

    お世話になります。 早速ですが、 以前、以下のような、「UNIXファイルの文字列を置換する」プログラムを Cscript で記述する方法を教えていただいたものですが、 cscript //nologo foo.vbs < t22.org > t22.txt ====foo.vbs==================================================== Do While Not WScript.StdIn.AtEndOfStream str = WScript.StdIn.ReadLine WScript.StdOut.Write replace(str,"abc","xxx") & vbLF Loop 今回、これをさらに、 Cscript で「置換するファイル」と「置換する文字列」も指定するプログラム にしたいと思い記述してみたのですが、下記のような問題が発生します。 「置換後のファイルの最後に改行文字が入ってしまいます。」原因がわかりません。 cscript //nologo f00.vbs t22.txt aaa xxx ====foo.vbs==================================================== Dim myFile Dim myRec Dim fso Dim txt, wd1, wd2 txt = WScript.Arguments(0) wd1 = WScript.Arguments(1) wd2 = WScript.Arguments(2) WScript.Echo txt WScript.Echo wd1 WScript.Echo wd2 Set fso = CreateObject("Scripting.FileSystemObject") Set myFile = fso.OpenTextFile(txt) myRec = myFile.ReadAll myRec = replace(myRec,wd1,wd2) myFile.Close Set myFile = fso.CreateTextFile(txt) myFile.WriteLine (myRec) myFile.Close =============================== このコードのどこに問題があるのでしょうか? 読み込んでいるファイルは、Shift-JIS LF改行のファイルです。 あるいは、 もっと簡単な記述方法等ありましたら、ご意見、ご指導ください。

  • c言語 文字数のカウント 合わない

    こんにちは. c言語のプログラムを書いて疑問に思ったことがあるのでお尋ねします.以下のプログラムで,data.txtに書かれている文字を読み取り,総文字数,スペース,タブ,ニューラインの数をカウントしようと思いました.スペース,タブ,ニューラインは正しくカウントするのですが,総文字数char_counterの数が合いません.ファイルから文字を読み取る時に使った,loop_counterもchar_counterと同義だと思いloop_counterを表示させてみたところ,こちらは文字数を正しくカウントしているようです. I am checking how it works. という文字列が入ったファイルなのですが,char_counterは100文字を越えてしまいます.どうしてloop_counterとchar_counterで違う値が出てしまうのでしょうか?解答をお待ちしております.その他正しく動いている部分に関しても,変な書き方のところがあればそれも指摘して頂ければ嬉しいです. なお,原因解明のために試行錯誤していて,ファイルの読み取りでは配列の[]の中身を足していき,文字を比較する際にはポインタの値を足していくという変なプログラムになっています.ご了承下さい. #include <stdio.h> #include <stdlib.h> #define BUF_SIZE (256) #define EXIT_FAILURE (1) int main() { FILE *fp; char read_line[BUF_SIZE]; int loop_counter = 0; fp = fopen("data.txt", "r"); if(fp == NULL) { printf("file open error\n"); exit(EXIT_FAILURE); } while((read_line[loop_counter] = getc(fp)) != EOF) { loop_counter++; } read_line[loop_counter] = '\0'; fclose(fp); if(fp == NULL) { printf("file close error\n"); exit(EXIT_FAILURE); } /* this counts the whole char numbers including space*/ int char_counter = 0; int space_counter = 0; int tab_counter = 0; int newline_counter = 0; char *read_line_address; read_line_address = &read_line; while(*read_line_address != EOF) { char_counter++; switch(*read_line_address) { case ' ': space_counter++; break; case '\t': tab_counter++; break; case '\n': newline_counter++; break; default: break; } read_line_address++; } printf("%s\n", read_line); printf("space %d ", space_counter); printf("tab %d ", tab_counter); printf("newline %d ", newline_counter); /* printf("whole chars %d\n", char_counter); */ printf("whole chars %d\n", loop_counter); return 0; }

  • CGIで取得したログの改行と表示したときの修飾方法

    HTMLで入力した項目を下記のCGIのファイルオープンでテキストとしてデータを取りますが、追加するように指定しているので1回目の入力の後、改行して2回目の入力をしたく、最後に\nをつけています。自分のPCをウェブサーバーにして実行すれば改行されましたがプロバイダーに載せると改行しませんでした、どなたかご教授をお願いします。また、このテキストファイルを(2)のようにして他のサイトで表示しようと考えていますがこのファイルに書かれた文字のフォントなど修飾するにはどのようにするのでしょうか? ちなみにHTML&CGI歴14日ぐらいですので、厚かましいのですが分かりやすくお願いいたします。 { # ファイルに保存 open (FH,">>file1-$number.txt");# 上書きモードでオープン $line=<FH>; @filew=("$name, $object,$time,$reason\n"); print FH @filew; close(FH); exit; } (2)<IFRAME src="cgi-bin/file1-1.txt"

    • 締切済み
    • CGI

専門家に質問してみよう