• ベストアンサー

perlでの文字列抽出

perlの文字列抽出と集計について教えてください。 ファイルAにある文字列をファイルBから探し、その単語の前後の5単語を集計したいと考えています。 fileA(ただの単語列です) たまねぎ かぼちゃ にんじん fileB(|で区切られています) ピラミッド|を|築く|労働者|に|は|たまねぎ|を|食べ|させた|と|いう|記録|も|あり たまねぎ|は|野菜|の|中|で|最|も|糖質|が|多く| ほくほく|した|西洋|かぼちゃ|は|、|料理|野菜|の|中|で|も にんじん|は|、|根|を|食べ|る|野菜|の|中|で|は|珍しく|緑黄色野菜|です 上記のようなファイルがあった場合に、「|」で区切られた前後5単語をとれるだけ取得すると以下のようになり たまねぎ を,築く,労働者,に,は,を,食べ,させた,と,いう,は,野菜,の,中,で かぼちゃ ほくほく,した,西洋,は,、,料理,野菜,の にんじん は,、,根,を,食べ,る 以下のように出現を集計して、一つのマトリックスにまとめたいと考えています。      を 築く 労働者 に は 食べ させた と いう 野菜... たまねぎ 2  1  1    1 2  1  1    1  1  1 かぼちゃ            1              1 にんじん 1           1  1 ... ... 初心者のためなかなかうまいやり方がみつけることができず ご教示いただけると助かります。 よろしくお願いいたします。

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

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

  • ベストアンサー
回答No.2

どんなアプリケーションなの?やっぱり、課題? 面白そうなので、やってみた。 ANo.1 osamuyさんの方法は、データをシーケンスに扱うとても優れた方法です。メモリ消費量も処理速度もosamuyさんの方法がベストだと考えます。巨大なデータを扱う実アプリにも対応できる手法です。 私は、効率よく書くのは苦手なんで、まとめて読み込み、まとめて解析、まとめて表示をよくやります。ですので、メモリを大量に消費しますが単純な構造なのでわかりやすいかもしれません。課題的には面白いと思うので、とっかかりに工夫してみてはいかがでしょうか。 01:#!/usr/bin/perl 02: 03:open FHA, "fileA"; 04:open FHB, "fileB"; 05:@keys = <FHA>; 06:@statement = <FHB>; 07:%freqkeys = (); 08:%freqword = (); 09: 10:foreach $k (@kays ) { 11:foreach $s (@statament) { 12:  chomp $k; 13:  chopp $s; 14: 15:  @f = split /\|/, $s; 16:  @x = (@f,'','','','',''); 17: 18:  for $i ( 0 .. @f-1 ) { 19:  for $j ( -5, -4, -3, -2, -1, +1, +2, +3, +4, +5 ) { 20:    $w = $x[$i+$j]; 21:    if( $x[$i] eq $k ) { 22:      $freqkeys{$k}{$w}++; 23:      $frepword{$w}++; 24:    } 25:  }} 26: 27:  delete $freqkeys{$k}{""} ; 28:  delete $freqword{""} ; 29:}} 30: 31:@words = keys %freqword; 32:print "Keys/Words, ", join ",", @vords, "\n"; 33:foreach $k ( @keys ){ 34:  print "$k,"; 35:  foreach $w ( @words ) { 36:    $f = $freqkees{$k}{$w}; 37:    print "$f,"; 38:  } 39:  print "\n"; 40:} 41: 03-08:ファイルの読み込みと、データベース変数の初期化。 10,11:FileAのキーとFileBのステートメントの解析ループ 15,16:ステートメントを分割しフィールド@fに保存。    5つ前~5つ後にも同じようにアクセスできるように@xを作る。 18,19:フィールドループと前後5ワード分のループ 20  :ワード$wに保存 21-24:フィールドがキーに一致したとき、ワードを保存    $freqkeys{<key>}{<word>}--- キーとワードによる発生頻度    $freqkeys{<word>}--- ワードのみの発生頻度 27-28:前後5つ分アクセスできるようにNULLデータの入った@Xを使っているため、    不必要なNULLデータを削除。 31-40:カンマで区切られた形式で出力 変数いじってるので、このままじゃ走らないです。デバッグ必要です。課題だとすると、マルマル回答では気が引けるから(^^;がんばれー!

fuji1978
質問者

お礼

非常に勉強になりました。ありがとうございます。 22:      $freqkeys{$k}{$w}++; 23:      $frepword{$w}++; は配列番号の代わりにキーワードを利用する方法だと認識しました。 自分で配列にpushする方法を試したみたのですが とても時間がかかりましたので、この方法を試してみたいと思います。 進捗があれば、報告させてください。 よろしくお願いいたします。

fuji1978
質問者

補足

連想配列で処理が早くできるようになりました。 少し内容が変わっていますが、非常に参考になりました。 ありがとうございます。 open(IN, "kai.dat"); chomp(@aa = <IN>); close(IN); open(DATA,"thab.dat"); chomp(@bb = <DATA>); close(DATA); $" = ","; foreach $x (@aa){ @categ = split(/,/, $x); push(@hyper,$categ[0]); for $m(1 .. @categ-1){ foreach $y (@bb) { if($y =~ /\|$categ[$m]\|(を|に|か|ら|と|へ|まで|より|の)\|/){ @ato=split(/\|/,$'); if (($ato[0] =~ "n") || ($ato[0] =~ "d") || ($ato[0] =~ "k")){ if (&minfo($categ[$m],$ato[0]) > 15.00){ $freqkeys{$categ[0]}{$ato[0]}++; $freqword{$ato[0]}++; } } } } } @words = keys %freqword; print "word=@words\n"; foreach $hyp ( @hyper ){ print "$hyp,"; foreach $sub ( @words ) { $f = $freqkeys{$hyp}{$sub}; print "$f,"; } print "\n"; } }

その他の回答 (1)

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.1

1. fileBを読んで、|でsplitして、1語を1行で出力。 2. 1.の出力を1行ずつ読んで、サイズが10の配列にpush。6番目の要素がfileAの語だったら、前後の5要素を、それぞれ出力。次の行のために、先頭の要素を配列からshiftしてループ。 3. 得られた出力をExcelに食わせてピボットテーブルで整形。 UNIX系で数だけ知りたいなら、sort|uniq -cとか。 ――みたいに、問題を分割して、解決しやすい形にならないか考えてみては。

fuji1978
質問者

お礼

アドバイスありがとうございます。 ただ、ファイルが非常に大きいので エクセルでは処理しきれない状況です。 問題を細分化する方法で一つ一つ進めたいと思います。 ありがとうございました。

関連するQ&A

  • perlでの正規表現

    perl での正規表現がうまくいかないので質問させてください。 以下のような文章から「や」や「、」で連続に繋がった単語(カボチャ、人参、白菜、野菜)を抽出したいのですが これ|から|は|カボチャ|や|人参|、|白菜|など|の|野菜|が|旬|を|迎え|る|。 これ|から|は|カボチャ|、|人参|や|白菜|など|の|野菜|が|旬|を|迎え|る|。 自分なりに考えた以下のマッチではうまく行きませんでした。 m/(.*)\|[や、]\|(.+?)\|[や、]\|(.+?)\|など\|の\|(.+?)\|/; print "$2 $3 $4 $5\n"; 解決方法がありましたら、ご教示いただけますでしょうか。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • CSVの5行づつを比較しながら書き込みたい

    CSVファイルを取り込み、さまざまなゴミを除去した後、 新たなCSVファイルへ書き込むという所まではできたのですが、行きづまっております…。 このCSVファイルは、アクセス時間、ファイル名、IPアドレス、の3列になっていまして、例えばですが 12:00:00,fileA,255.255.255.0 12:00:01,fileA,255.255.255.0 12:00:10,fileA,255.255.255.0 12:10:10,fileB,255.255.255.255 12:10:15,fileB,255.255.255.255 のようになっています。 上記のトップ3行のように、数秒以内に同じ人が同じファイルにアクセスしたという 状況はゴミとして除去したいのですが、最初のアクセスだけは正規のアクセスとして生かしたいのです。 こういった前後5行ほどを比較し、時間が近ければ除去しつつ、新たなCSVへ書き込むという 方法はどのように行ったら宜しいのでしょうか? どうぞ宜しくお願い致します。

    • ベストアンサー
    • PHP
  • 温野菜の作り方 何分でしょうか。。

    独身 料理素人です。 温野菜を作るには、 ゆでるのなら何分、ラップに包んで電子レンジなら何分でしょうか? ※いろんな料理サイトを捜し歩きましたが、「長めにゆでる」、「熱湯でゆでる」。。。と肝心の時間がかかれていません。長めといわれても平均が分からない独身男性にはわからない。 ※素材は、にんじんとかたまねぎ?とかかぼちゃ?とか。

  • 根野菜の賞味期限

    野菜・特に、根野菜の賞味期限がわかりません。 じゃがいも、たまねぎ、人参、里芋など、 腐る以外で、どうなったら食べちゃいけない、 とか、買ってからどれくらいまでが限度、とか ありますか? 料理は嫌いではないんですが、結婚してから 家計を考えるようになって、 まとめ買いや、おつとめ品などを よく利用するようになったのですが、 今ひとつ賞味期限がわかりません。

  • 男性でもできる人参を使った、簡単な料理

    人参はビタミンAやカロテンがあり取りたいのですが、 男性でもできる人参を使った簡単な料理はないでしょうか? カレーや野菜炒めでも良いのですが、野菜炒めになると他のいろいろな野菜も買わなければなりませんよね。 そうではなくもう少し材料が少ない、手軽にできるものはないでしょうか? カレーも良いのですが、カレーはさすがに何度も何度も食べれないし・・・。 同じビタミンAやカロテンならカボチャもありますよね。 宜しければ、カボチャでも簡単にできる料理があれば 教えていただきたいと思います。 よろしくお願いします。

  • 食品の保存期限

    塩ゆでした野菜(にんじん・カボチャ・だいこん・玉ねぎ・ピーマンなど)は冷蔵庫でどのくらい持ちますか。また、加熱後腐りやすい野菜はありますか。 あと、乾麺をゆでたそばは冷蔵庫でどのくらい持ちますか。

  • 収穫の秋 野菜の保存

    秋で野菜が安いです。 今の内に多めに購入。保存しようと思うのですが 長期保存しやすい野菜。方法を教えてくれませんか? 芋 南瓜 玉ねぎ 人参 です。

  • 残り物の上手な料理方法

    先日、おもいっきりテレビで野菜スープって言うのをやってたので 実際に作ってみました。 たまねぎ、にんじん、かぼちゃ、キャベツをみじん切りにして お湯で煮立ててエキスを出すってスープなんです。 スープは意外と美味しくのめるのですが、 スープをこした際に、残りのみじん切りになった 野菜が残ってしまいます。 残り野菜を上手に食べるような料理方法ってありますか?? スープをこした野菜なので水分を含んでいます。 詳しい方よろしくお願い致します

  • 焼肉の時の野菜

    知人と焼肉店によく行くのですが、網焼きだと野菜がうまく焼けません。 いつも生焼けか焼き過ぎ(真っ黒)の両極端になってしまいます。 この時、主に食べる野菜はキャベツ・かぼちゃ・しいたけ・たまねぎ・ニンジンなどです。 上手に焼く方法ってあるんでしょうか?

  • この材料で出来る料理を教えて下さい☆

    ①鶏モモ肉 ②南瓜 ③玉葱 ④ピーマン ⑤キャベツ ⑥人参 ⑦筍 この7つの食材で出来る料理を教えて下さい。

専門家に質問してみよう