• ベストアンサー

重複文字列の消去について

同じファイル内での重複文字列の消去について教えてください。 以下のようなファイルがあった時に ---text--- 100 フランチャイズ 98 二酸化炭素 76 ワールドカップ ・・・ 4 排出二酸化炭素 3 直営フランチャイズ 3 サッカーワールドカップ 1 2009年ワールドカップ ------- 「排出二酸化炭素、直営フランチャイズ、サッカーワールドカップ、2009年ワールドカップ」はファイル上位のキーワードと重複する部分があるので消去したいと考えています。 まず、以下の処理で不要部分の抽出を考えてみたのですが、ループが一度しか回らずに処理が停止してしまいました。どのようにするとよいでしょうか。 よろしくお願いいたします。 my $file = "text"; open( my $fh, "<", $file ) or die "Cannot open $file: $!"; my $lineheader = ''; while (<>) { $lineheader = (split)[1]; while(my $line = readline $fh){ if($line =~ /$lineheader/){ print $line; } $lineheader = ""; } }

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

質問者が選んだベストアンサー

  • ベストアンサー
  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.2

今までに出てきたキーワードを変数に記録しておけば、 いきなり「既出キーワードのある行は出力しない」という処理ができます。 ---ここから--- my $file = "text"; open( my $fh, "<", $file ) or die "Cannot open $file: $!"; my @keywords; # 今までに出現したキーワードを記録する配列変数 #ファイルの各行について処理 while (<$fh>) { my $lineheader = (split)[1]; my $found = 0; #既出キーワードが含まれるかどうかをチェック foreach my $keyword ( @keywords ) { if ($lineheader =~ /\Q$keyword\E/) { #既出の場合、フラグを立ててチェックループ脱出 $found = 1; last; } } if (!$found) { #既出キーワードのない行は出力 print; #既出キーワードに項目追加 push(@keywords, $lineheader); } } ---ここまで---

fuji1978
質問者

お礼

ありがとうございます。 処理を流してみたところうまく実行できているようです。 ただファイルが巨大なので、時間がかかってしまっています。 なんとか処理はできそうですが、次回のためにも はじめの質問で申し上げておくべきでした。 ありがとうございました。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「ループが 1度しかまわらない」というのは, どこのループのことですか? $fh のオープンはその位置でいいのですか?

fuji1978
質問者

補足

一番はじめのwhile (<>) ループです。 一行目のキーワードについてのみ処理がされ 二行目のキーワードについては処理されません。。 $fh で読み込んだファイルと標準入力から読み込んだファイルは同じものです。

関連するQ&A

  • ファイル内で重複している数と重複した回数

    開くファイルの中身は数字のみ。 1行に一つずつ数字が入っており、 それが何行にもわたり続くファイルです。 ファイル内で重複している数と重複した回数を数えたいです。 以下のようなスクリプトを使ったのですが、 結果を表示させようとすると global symbol"$hash" requires explicit package name. にエラーが出ます。 何故なのでしょうか。 use strict; # ファイルを開く my $INPUT_FILE; open ($INPUT_FILE, ">numbers.dat") or die “Can't open. \n”; # それぞれの数をハッシュキーにする。そして対応するバリューを同じ数を見つける度毎にカウントアップする。 my %hash = (); while (my $line = readline($INPUT_FILE)) { chomp $line; $hash{$line}++; } # キーでソートし、結果を表示する。 my @keys = sort keys %hash; foreach my $key (@keys) { print “$key is found $hash{$key} times\n”; } close ($INPUT_FILE) or die “can't close the file\n”;

    • ベストアンサー
    • Perl
  • パターンマッチ

    perlの勉強を始めてまだ1週間くらいの初心者です。ゼミでperlのプログラムを渡されて解読するように言われperlを勉強しています。早速、質問なのです。 $fhはspecファイルを読みこんでいます。 1:while(my $line=<$fh>){ 2: chomp $line; 3: next if($line=~ /^\s*\#/ || $line=~ /^\s*$/); 4: : 5: : と続いて行きます。質問はプログラム3行目の $line=~ /^\s*\#/ || $line=~ /^\s*$/ の意味です。この意味がいまいち良く分りません。どなたか教えていただけないでしょうか。 ちなみにこのプログラムはUNIX MAGAZINE2005.9で紹介されたgenhtpgというシステムのプログラムと聞いています。

    • ベストアンサー
    • Perl
  • ファイルを読み込んだ時に同じ文字が重複した場合.kファイルに書き込まない

    こんにちは。 テキストファイルの内容が KENIA=ナイル川 NORTH=小さな旅人 KENIA=せせらぎ 上記のファイルを読み込んだ際に下記のコードで実行すると .hファイルに書き込まれる内容は..... KENIA NORTH KENIA ですが同じ言葉が出現した場合(重複した場合)ファイルに書きまないようにしたいと思っています。すなわち KENIA NORTH   としたいと思っています。 この場合どうしたらいいでしょうか?? テキストファイルは例であり内容は不規則ですので。。。。 力をお貸しください。よろしくお願いします。 #include<stdio.h> int makemoutputhleftside(); int main(int argc,char **argv){ makemoutputhleftside(argv[1]); } int makemoutputhleftside(char sum[64]) { char buf[1024]; char cPid[256]; int iOid; FILE *ft; FILE *fh; char filename[64]; int i; strcpy(filename,sum); strcat(filename,".txt"); ft = fopen(filename,"r"); fh = fopen("moutput.h","w"); if (ft == NULL || fh == NULL) { printf("開けないファイルがあります。\n"); return 1; } /* ファイルを1行ずつ読み込む処理 */ while (fgets(buf, sizeof buf, ft) != NULL) { strcpy(cPid, strtok(buf, "=")); fprintf(fh, "#define %s \n", cPid); fclose(fh); fclose(ft); return 0; }

  • Perlでファイルを読み込みタグを削除する方法

    以下のようなソースを書きました。 HTMLファイルを読み込み、タグを全て削除して他のファイルに書き込むソースです。 しかし、上手く動作しません。 問題点を教えていただけませんでしょうか。 お願いします。 #!/usr/local/bin/perl package www3sub2; sub main(){ open(FH, "<googlefile3_.txt"); my @file = <FH>; close(FH); open(OUTB,"> googlefile6.txt"); foreach(@file){ my $line = $_; $line =~ s/<("[^"]*"|'[^']*'|[^'">])*>//g; print OUTB "$line"; close(OUTB); } } 1;

  • 重複文字を出力させない!!

    こんにちは!! ご質問させてください。 右辺値のダブルクオートくくりの 文字列をテキストから読み込みファイルに書き込む処理ですが..... うまく取れません。下記にソースコードを提示しましたので 一読の上アドバイスいただけたらと思います。 テキストファイルのないようは k="seikyo"-"himawari" k="north"+"seikyo" これを読み込んだ場合.tファイルに書き込む内容は seikyo himawari north seikyo ですが重複した場合は書き込まないようにプログラムしたつもりです。 seikyo himawari north としたいと思っています。 希望通りの形にならないので皆様どうか お力をお貸しください。よろしくお願いします。 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<syslog.h> #define MAX_REC_A 256 #define MAXFIELD 128 #define BUFFLEN 256 #define MAX 10000 #define MBF 1024 int makemoutputhrightside(); int main(int argc ,char **argv) { makemoutputhrightside(argv[1]); } /* 右辺の値をとって.tファイルに書き込む関数 */ int makemoutputhrightside(char sum[BUFFLEN]) { FILE *ft; FILE *fh; int c; char cPid[BUFFLEN]; char *p; char *q; char *str[BUFFLEN]; int flag = 0; int i = 0; int n = 0; int k; char filename[64]; char cdmy[MAX]; strcpy(filename,sum); strcat(filename,".txt"); ft = fopen(filename, "r"); fh = fopen("moutput.t", "a"); if (ft == NULL || fh == NULL) { syslog(LOG_ERR,"開けないファイルがあります。\n"); return 1; } //ファイルを1文字ずつ読み込む while ((c = fgetc(ft)) != EOF) { switch (c) { case '"': flag = 1 - flag; /*右のクオート*/ if (flag == 0) { cPid[i] = '\0'; p = strcpy(cdmy,cPid); for(k = 0;k < n;k++){ if(*str[k] != *p) continue; if(strcmp(str[k],p) == 0) break; } if(k < n) continue; q = malloc(strlen(p) + 1); strcpy(q,p); str[n] = q; fprintf(fh, "%s ",q); i = 0; } n++; break; case '\n': if (flag == 1) { cPid[i] = '\0'; fprintf(fh, "%s \n", cPid); } flag = 0; } i = 0; break; default: if (flag == 1) { cPid[i] = c; if (i < BUFFLEN - 1) { i++; } } break; } } /* ファイルの最後が改行じゃなかった場合 */ if (i>0) { cPid[i]='\0'; fprintf(fh,"%s\n",cPid); } fclose(ft); fclose(fh); return 0; }

  • 文字列の比較の仕方が分かりません

    フォームから入力された文字列をデータファイルの中から検索し、重複していなければ追加登録したい。 ・問題点 重複していても登録できてしまう。 昨日からperlを触り始めたばかりなので、基本的な部分が分かっておらず、 おかしい部分が多々あるかもしれませんが、ご指導よろしくお願い致します。 データは全て"["から始まるので、登録できませんの部分は、簡単な入力チェックです。 -------------------------------------------- test.html <html> <head> <meta http-equiv="Content-type" content="text/html; charset=UTF-8"> </head> <body> <form action="test2.cgi" method="post"> <input type="text" name="shirolist" size="50" /> <input type="submit" name="submit" value="送信" /> </form> </body> </html> -------------------------------------------- test2.cgi #!/usr/local/bin/perl use utf8; use CGI; $q = new CGI; $flag = 0; $data = $q -> param('shirolist'); $data =~ s/\s+//g; open(IN , "<:uft8" , "data.dat"); while($line=<IN>){ if ( $line eq $data ) { $flag = 1; } } close(IN); if($flag == 0){ if ($data =~ /^\[/) { open(OUT,">>data.dat"); print OUT "$data\n"; close(OUT); $pr="を登録しました"; } else { $pr="は登録できません"; } } else { $pr="は登録済みです"; } print "Content-Type: text/html; charset=UTF-8\n"; print "$data $pr<br>\n"; ※Yahoo知恵袋で同様の質問をしましたが、 回答者への個別のコメントや追加質問が出来ず、 非常に使いづらく感じたのでこちらに投稿させて頂きました。

    • ベストアンサー
    • Perl
  • Data::Dumper;でダンプ後表示した文字列\x{30fc}...

    お世話になります。 下記のスクリプトを使ってrssファイル内をuse Data::Dumper;でダンプして表示してみたのですが、rssファイルがutf8で記述されているせいか 表示時に日本語の所が\x{30fc}のような文字列になってしまいます。 これをshiftjisで表示させたいのですが、試行錯誤してもうまくいきません。 どなたかご教授いただけませんでしょうか。 #!/usr/bin/perl BEGIN{ $| = 1; print "Content-type: text/html\n\n"; open(STDERR, ">&STDOUT"); } use XML::RSS; use Data::Dumper; my $rss = new XML::RSS; #表示形式の違いで1と2がある。 $Data::Dumper::Indent = 1; use open IN => ":utf8"; # 入力をUTF8とする use open OUT => ":shiftjis"; #use open ":std"; #use Encode; #use encoding 'shiftjis', STDIN=>'utf8', STDOUT=>'sjis'; #binmode STDOUT, ":encoding(utf-8)"; #binmode STDOUT, ":encoding(shiftjis)"; #binmode STDOUT, ":encoding(euc-jp)"; #use open ":encoding(shiftjis)"; # rssをセット。 open my $fh, '< ./test.rss'; my $text = join undef, <$fh>; close $fh; # rssをパース $rss->parse($text); # ひとまず中見を知る為にダンプしてみる print "Content-type:text/html;charset=Shift_JIS\n\n"; print "<html><head>\n"; print "<title></title></head>\n"; print "<body>\n"; print Data::Dumper->Dump([$rss]);

    • ベストアンサー
    • Perl
  • 複数行に渡る文字列の置換

    こんにちは、Perl初心者です(プログラミング全般の初心者です)。 カレントフォルダ内のテキストファイルに対して、文字列置換をするスクリプトを書こうとしています。具体的には、以下のようにストリングIDの直下に改行のみの場合(ストリングがない)は、[BLANK]という文字列を挿入したいと思っています。 TEXT_STRING_ID_001<改行> <改行> <改行> TEXT_STRING_ID_002<改行> 入門書やこのサイトの皆さまのお力を借りて、なんとか以下のようなリストを書きエラーなく置換処理ができるところまでは確認できました。 しかし、この方法だと結局1行ずつ処理していることになるので、「s/\n{3}/\n[en]\n/gm」のような置換ができません(mオプションをつけてもダメなようです)。 この問題を解決する良い方法はないものでしょうか。 (もしかすると、処理の仕方を根本から変えないといけないのでしょうか) 以下、現状のリスト: use strict; use warnings; my $dirname = '.'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless (-f $dir); next unless ($dir =~ /\.txt$/); print $dir, "\n"; open(FILE, $dir) or die "$dir: $!"; my @file = <FILE>; close(FILE); foreach my $line (@file) { $line =~ s/\n{3}/\n[BLANK]\n/gm; } open(NEWFILE, "> $dir") or die "$dir: $!"; print NEWFILE @file; close(NEWFILE); } closedir(DIR);

    • ベストアンサー
    • Perl
  • Pythonで重複無しの出題をしたい。

    Pytonで初歩的なcodeを書いております。 十個の四文字熟語があります。 重複のない四文字熟語を表示したいのです。 (1)のcodeでは上手く行くのですが、(2)の様にテキストファイルから読み込むと重複します。 多分while関数を使って重複が有ったら、再度randomで重複しないデータを抽出しろとでもやるのでしょうが、上手く行きません。 while以降どの様にcodingするのか、或いはそのほかの方法を教えて頂ければ嬉しいです。 宜しくお願い致します。 (1) リストから重複無しの熟語を表示する---OK ---------------------------- import random 四文字熟語=[ '0 百花繚乱', '1 疾風迅雷', '2 明鏡止水', '3 不撓不屈', '4 国士無双', '5 魑魅魍魎', '6 行雲流水', '7 花鳥風月', '8 天下無双', '9 行雲流水' ] 空リスト = [] for カウンター in range(10): 一時保存 = random.choice(四文字熟語) while 一時保存 in 空リスト: 一時保存 = random.choice(四文字熟語) 空リスト.append(一時保存) print(一時保存) これは重複無しの熟語を表示します。 --------------------- (1) テキストファイルから、重複無しの熟語を表示する---NG import random file = open("四文字熟語.txt") lines = file.readlines() file.close() for line in lines: line = line.rstrip("\n") temp = random.choice(lines) print(temp) Shellには、 7 花鳥風月 6 行雲流水 6 行雲流水 7 花鳥風月 2 明鏡止水 9 行雲流水 9 行雲流水 8 天下無双 7 花鳥風月 0 百花繚乱 -------------------------- このほうほうだと、こんな風に表示されます。

  • Perlでの一括アップロード

    同じファイルを違うファイル名で一括でアップロードしたいのですが。 最初の一つしか正常にアップされません。 残りのファイルは正しいファイル名で作成はされるのですが、0バイトの状態です。 原因としてはファイルを書き込む Whileの中のprintしている部分かと思われます。 ちなみにバイナリデータも取得できています。 *このソースはファイルのアップ部分だけで、 実際にはforeachの中で関数として呼ばれています。 エラー関数や、モジュールの呼び出し部分は省略しています。 仕様モジュールCGI.pm ソースは以下のとおりです。 ご教授の方よろしくお願いいたします。 # 最大許容サイズ(KByte) my $maxsize = 300; # 保存先ディレクトリ my $logfiles = "./file"; # アップロードを許可するファイルの種類 my %hash_mime = ( 'text/html' => 'html', 'image/jpeg' => 'jpg', 'image/pjpeg' => 'jpg' ); # ファイル取得 my $fH = $query->upload('filename'); # エラーチェック if ($query->cgi_error) { my $err = $query->cgi_error; &error("$err") if ($err); } &error("File transfer error.") unless (defined($fH)); # MIMEタイプ取得 my $mimetype = $query->uploadInfo($fH)->{'Content-Type'}; # 保存するファイル名を取得 my $set = &set_name($mimetype); # ファイル保存 my ($buffer); open (OUT, ">$logfiles/$set") || &error("Can't open $set"); binmode (OUT); while(read($fH, $buffer, 1024)){ print OUT $buffer; } close (OUT); close ($fH) if ($CGI::OS ne 'UNIX'); chmod (0666, "$logfiles/$set");

    • ベストアンサー
    • Perl