• ベストアンサー

Perlによる文字の抽出方法

プログラム初心者なので、あまりうまく説明できませんが、よろしくお願いします。 あるテキストデータから、一部分だけをだけを取り出したいのです。 例えば、 例1  ■見出し1■   ・データ1   ・データ1  ■見出し2■   ・データ2   ・データ2  ■見出し3■   ・データ3   ・データ3 のようなデータから、■見出し2■とその中にある内容(・データ2の内容は いくつもあるものとする)でだけを取り出したいのですが、どうすれば よいのでしょうか?■見出し*■をkeyとしてハッシュに入れて、複数個 の値をつればようのでしょうか? それとも、他の方法で処理したほうがよいのでしょうか? 文字列から文字列までの指定というのは、どうすればよいのでしょうか? 回答よろしくお願いします。

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

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

  • ベストアンサー
  • tailkuppa
  • ベストアンサー率53% (52/98)
回答No.1

むちゃくちゃ長くて申し訳ありません。 回答しようとしてみて、いろいろなことが気になってしまって長くなりました。 間違いはないように努力していますが、もっといい解決方法はあるかも知れません。 ハッシュのキーは、重複が許されません。 1つのユニークなキーに対して、1つの値しか対応が付けられません。 ただし、値の型には参照も許されるので、リストの参照を対応づけすることも可能なはずです。回答者は、ややこしくなるのでやったことがないのですけど。 ■見出し2■ ・データ2 ・データ2 のように、同じものが並んでいるように書いてありますが、並んでいるデータ2の内容は同じものですか? それとも、何種類かありますか? 同じ種類のが何行かあるとして、それはまとめて1つにしてもいいですか? 1種類で、まとめてもOKなのであれば、単純にハッシュにすれば可能だと思います。 最後に結びつけた値がキーに対応する値になります。 ■見出し1■ => ・データ1 ■見出し2■ => ・データ2 データに複数種類が可能だとすると、ハッシュでは対応できないと思います。 ・データ? の内容が■見出し?■に関係なくすべてのデータ内でユニークであることが確実なのであれば、キーと値の関係を逆にすることで検索可能だと思います。 ・データ1(その1) => ■見出し1■ ・データ1(その2) => ■見出し1■ ・データ2(その1) => ■見出し2■ 上記のいずれでもない場合は、下記のような感じで一つ一つ見ていくしかないと思います。 データが多い・検索回数が多い場合は重たい処理になるかも知れません。 その場合には DB を使うなり、もっと扱いやすい形式に変換するなりした方がいいと思います。 下記ではカンマ区切りのテキストデータで返していますが、#★ 以下のように変更すれば、配列(の参照)でも値を返せます。 特にカンマ区切りにする必要も、改行をとる必要もありませんが、この方が見栄えがいい(というか、ファイルに出力した際に使いやすそうな)のでそうしています。 各データの行を区別して扱う必要がない(複数まとめて扱いたい)のであれば、単純に連結してもOK です。 改行で切り分けることもできます(split(/\n/, 複数行データ))。 文字列の検索については "perl" と "正規表現" で検索してみると、いろいろ見つかると思います。 数字なので、(.+) ではなく(\d+) でもいいかと思いましたが、どうやら全角数字は駄目みたいです。 ↓以下がスクリプトです。 #/usr/bin/perl # データをグローバル変数 @data に読み込む open(IN, "データファイル名") || die "データファイル名 open 失敗\n."; my $key = ""; @data = ; close; my $val; my $ii; $val = kensaku("1"); foreach $ii (split(/,/,$val)) {#★ foreach $ii (@$val) { print $ii . "\n" ; } exit; # メモリ内を検索する sub kensaku { my $num = $_[0]; # 引数: 見出し番号(全角/半角に注意) my $line; # 現在行 my $value = ""; #★ my @value; foreach $line (@data) { if ($line =~ /■見出し$num■/) { #目的の見出し $key = $line; } elsif ($line =~ /■見出し(.+)■/) { #目的外の見出し $key = ""; } else { # 見出し以外 if ($key ne "") { # 目的の見出し以下のデータ項目 chop $line; # 改行を取る。場合によって取らないことも可 if ($value eq "") { # 最初 $value = $line; } else { # 2 個め以降は区切り文字 "," で区切って連結 $value =. "," . $line } #★ if で場合分けせずに push @value, $line; } } } return $value; #★ return \@value; }

cassis_r
質問者

お礼

ありがとうございました。 解決することができました(^^)

cassis_r
質問者

補足

返答が遅くなってしまって申し訳ありません。 丁重な説明をして頂き、誠にありがとうございました。  今回、私がやりたい事は、多くの情報の中から、知りたい情報だけをを抜きだしてきて、それを携帯電話などのモバイル機器でも見やすくするように、編集できないかと考えています。  例えば学校などのHPなどで連絡事項のページがあったとすると、その大きな連絡事項群の中から、例えば、「休講情報」について知りたいとします。 それを、携帯でも情報を見やすくするために、余計なものを取り除いて、「休講情報」だけの、新しい容量の小さいwebページを作りたいのです。 ここで、情報源となるHTMLページには、休講情報の内容の数や範囲などは、こちらでは全く指定できません。  そのための処理をしたいのですがどうもうまくいきませんでした。タブと余計なスペースなどを削除することはできたのですが(本に書いてあった通りに書いただけですけど)、この1番メインとなる処理がうまくいきませんでした。 そこで、読み込んだデータから、部分的な抜き出し方法が知りたかったのです。 キーとなるものも、もしかしたら変化するかも知れませんし、その中の内容は、 もちろん変わってしまうと考えられます。扱いずらいデータですよね。。。。 先日、例としてあげたデータのように、どこかマークの間にはさまれている文字が 見出しとなっており、その後に書かれているものが内容だということは、変わらな いと思います。 もし、このようなデータを処理するのに良い方法がありましたら、御教授お願いいたします。

その他の回答 (1)

  • aton
  • ベストアンサー率47% (160/334)
回答No.2

今一つ質問の内容が理解できていないのですが,一応「Perlで多次元配列を実現したい」というふうに解釈しました。 Perlはnativeには多次元配列をサポートしてませんので,ふつうは join() と split() を使って疑似的に多次元配列的な操作を実現してやります。 join() は配列を文字列に変換する関数,split() は文字列を配列に変換する関数で,以下のように使います。 #↓元の配列 @midashi_array = ("データ", "データ", "データ"); #↓最初の '\n' は区切り文字。何でもいいが配列の値("データ")の中に含まれていないもの) $midashi_str = join('\n', @midashi_array); #↓これで文字列が配列に戻る。配列 @midashi_array と @midashi_array_new は同じ値を持つはず @midashi_array_new = split('\n', $midashi_str); あとはこれをcassis_rさんが考えておられるように"見出し"をキーに持つハッシュ(Perl用語だと「連想配列」)と組み合わせればご所望の処理は実現できると思います。 ◆値の格納 @midashi1 = ("データ1", "データ1", "データ1"); $midashi1_str = join('\n', @midashi1); $hash{'見出し1'} = $midashi1_str; ... ◆値の取り出し $midashi1_str = $hash{'見出し1'}; @midashi1 = split('\n', $midashi1_str); ... これをループで回すなり何なりして処理すればできると思います。

cassis_r
質問者

お礼

ありがとうございました(^^)

cassis_r
質問者

補足

回答ありがとうございました。 前回、私の問題に対する質問が曖昧だったので今回は、具体的に行いたかった処理補足させていただいきます。 No.1の回答者の方のところにも補足させていただいたので詳しい内容は、省略させていただきますが、他人が作ったHP(もちろん許可は頂いてあります)から欲しいデータだけを取り出したいのです。 そのための処理を行うのには、どうすれば効率が良いかなどを、もう一度よろしければ、お力を借りたいと思います。 あつかましいのですが、よろしくお願いいたします。

関連するQ&A

  • perlのexistsについて

    変数の値と別のハッシュのキーに一致するものがあれば、ハッシュの値を別のスカラー変数に代入したいのですが、その場合のプログラム例を教えてください!

    • ベストアンサー
    • Perl
  • Perlによる自動処理について

    前回の質問ではお世話になりました。 おかげで上手く動作させることが出来ました、ありがとうございます。 今回は自動処理について質問したいと思います。 ハッシュに入っている複数の文字列 (あい、あいう、あいうえ、あいうえお) を”あい”としてまとめ、カウントしたいです。 アルゴリズムとしては、前文”あい”が共通しているので、”あい”を含むものを検索してカウントすれば出来ると思うのですが、正規表現など開発の際に単語を指定せずに出来るものなのでしょうか? 少々伝わりにくいと思うので以下に要点をまとめます。 (1)ハッシュに入っている類似文字列について、ひとまとめにカウントしたい。 (2)その際、開発の段階で文字列を指定しない(正規表現のようにパターンを設けない)で、(1)の処理が出来るかどうか。 どのような形でも良いので、複数ある単語をひとつにまとめ、尚且つキーワードを設けないようなものと言われたので、私としても(2)をどうして良いのか分かりません。 実現可能か不可能かだけでも、ご意見頂ければ嬉しいです。 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • 指定した値より頭文字を抽出するには

    図のように、A列に下向に2000くらいまでのデータがあります。 指定の抜き出したい値より、A列の頭文字が一致する部分のみを抜き出したいのですが、マクロなどで一括で処理する方法はありますでしょうか? 列の指定は特になく、文字間ごとにセルが分かれていても構いません。

  • ハッシュ法でのデータ管理について教えてください

    ハッシュ法でのデータ管理をするプログラムを作りたいんですが長いことPASCALに触ってなかったせいか全く分かりません。 どなたか教えていただけないでしょうか??問題の概要は以下のようなものです。 表に登録するデータについては、キーは英数字からなる長さ8までの文字列でデータ本体は整数(型名はintegerでよい)です。 ハッシュ表のサイズは11とします。 ハッシュ関数は文字列xの各文字のASCIIコードの総和を11で割った余りとします。 さらにメニュー表示として入力した文字により行う操作を決定します。 どの文字がどのような操作を行うのかは以下のとおりです。 's' の場合: ハッシュ表に登録されている全レコードを,ハッシュ関数値毎に(キーの値とデータの両方を)すべて表示します. 'r' の場合: さらに「キーの値」と「データ」を入力し,すでに同じキーをもつデータがあれば「二重登録」として検出し,そうでなければ,そのレコードをハッシュ表に登録します. 'e' の場合: さらに「キーの値」を入力し,そのキーをもつデータがハッシュ表に登録されているならば, そのデータを表示します.さらに削除するかどうかを入力させて,削除する選択をした場合にはそのレ コードを削除します.そのキーをもつデータがハッシュ表にない場合には「そのキーをもつレコードが ないこと」を出力しますが,ハッシュ表には操作を加えません. 'i' の場合: ハッシュ表に登録されている全レコードを,キーの値が小さい順に表示します.ここで「キー の値の順」とは,文字列の辞書順のことを意味します.Pascal では,文字列a,b に対して,a がb より 辞書的順序が先(小さい) ときには「a<b」で表現できます. 'd' の場合: 「'i' の場合」の逆で,キーの値が大きい順に表示します. 'q' の場合: プログラムを終了します.具体的には,実行文部の最後の「end.」の直前までジャンプし ます. 長くなってすいません。ちょっとしたヒントでもいいので教えていただければ幸いです。

  • ハッシュ探索とはどういうイメージなのか?

    ハッシュ探索というのは「対象となるデータから一定の手順で算出したハッシュ値を用いてデータ本体の代わりに比較に用いる方式」ということですが、どういうものなのかイメージが思いつきません。 これはつまり、データ本体を「ハッシュ」という文字列に変換して、ハッシュ値として出力したものを、比較する(全ての文字列において比較する)というイメージでよいのでしょうか? もしそうだとしたら、ハッシュ値の長さ(文字列の長さ)に応じて(比較)処理時間が変わってくるのでしょうか? 例えば、(あくまで例です。) 6文字程度のハッシュ値→0.2秒で(比較処理時間が)終わる 3万文字程度のハッシュ値→3秒ぐらい(比較処理時間が)かかる ↑こういう風にハッシュ探索は文字列の長さに応じて処理時間が変化するのでしょうか? 回答のほうお願いします。

  • 【Perl】文字列をカウントしたいです。

    以下のようなテキストファイルがあります。(ここで出すのは例なので、本当は1万行くらいあります) 20927258 7092 20927258 7093 21167105 7092 21167105 10469 21167105 10470 21167105 10471 21167105 10472 21167105 10473 21167105 10474 この中に入っている文字列、例えば20927258や10474などがいくつあるかをカウントするためのプログラムを書きたいのですが、どのようにすればよいでしょうか?? 重複があるので、それは消したいです。つまりこの例でいえば 20927258は2つということにしたいです。 よろしくお願いします!!!!

  • perlでアドバイスをお願いします。

    あるテキストファイルが以下の内容で記述されているとします。 a   file1 a   file1 a   file1 b   file1 b   file1 b   file1 c   file2 c   file2 d   file2 d   file2 e   file2 e   file2 f   file3 f   file3 f   file3 上記のように列が二つあるテキストファイルについて、 2列目のfile名が1列目のどの値とひもづいて いるかを処理するperlプログラムを作ることを考えます。 出来上がったperlによって上記テキストファイルを処理した結果は、 file1は aとb file2は cとdとe file3は f とひもづいていることが分かる ということにしたいです。 これをperlプログラムで書くとき、条件として 一行一行を読みとるとき if ( $_ =~ /(\S+)\s+(\S+)/ ){ を使っています。 そのため$1と$2に現在行の1列目,2列目が与えられた後、 ハッシュと配列を組み合わせて考えた場合どのようにすれば いいのでしょうか。 また仮にテキストファイルの続きが存在し、 1列目がg 、2列目がfile1 の行があるとき 2列目で既に出てきた同じfile名はエラーとすることも考えた 場合どう記述するのか合わせてお願い致します。 長くなってしまい申し訳ないのですが、 ご指導ご鞭撻宜しくお願い致します。

  • Perlのソートについて

    ハッシュを利用して今ソートできるプログラムを作成したのですが、 重複するデータは除外されてしまうようで、どうしたら除外されずに ソートできるかを教えていただきたいです。 <例> 文字 よみ  No      橋  はし  1      橋  はし  3      箸  はし  2 というデータがあったとして、今のプログラムを実行すると・・・ <結果> 箸  はし  2 キーがよみなので3番目のデータだけ残ります。キーを漢字に したとしても1番目のデータは残らないのですが、どうしてらよいのでしょうか。 <理想的な結果>      橋  はし  1      箸  はし  2      橋  はし  3 一番いいのが上のような結果で、Excelのソートのような感じで、第1キーはよみで第2キーはNoとかのソートはPerlでできないでしょうかね?? どなたか分かる方がいたら教えていただきたいです。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • postで送られてきたパラメータが処理できない(perlCGI)

    postで送られてきたパラメータが処理できない(perlCGI) postメソッドで送信されてきたパラメータの値によって条件分岐しようとしているのですが どうも受け取ったパラメータがハッシュ値のはずなのにハッシュ値として処理できなくて困っています。perl自体初心者なのでなにか勘違いしている可能性が高いですが、意味不明で完全に行き詰っているのでよろしくお願いします。 (送信パラメータは{"key":"1"}) #!/usr/bin/perl read(STDIN, $data, $ENV{'CONTENT_LENGTH'}); print "Content-type: text/html\n"; print "\n"; print "$data{'key'}\n"; 確認のため上のコードのようにしてみたところなにも表示されません。 しかし最後の行でprint "$data\n"; という風に帰るとkey=1といった表示が出力されます。 $dataの中身が単純な文字列になっているかと思えばそうでもなく、かといって $data{"key"}, $data{'key'}で$dataの"key"に対応する要素を取り出そうとしてもなぜかできません。 postメソッドはただの値ではなくハッシュ値ではないと送れないみたいで多いに困っています。そもそもなんで連想配列を受け取っているはずなのに処理できないのでしょうか? 心当たりがある方、よろしくお願いします。

    • 締切済み
    • CGI
  • Perlでの文字列処理について

    プログラム初心者です。 Perlで下記のような文字列処理のプログラムの書き方がわからず、質問させて頂きました。 【内容】 FILE_A.txtが「!」マークで区切られていて、「!」マークの下行の文字列をIPアドレスの右横に移動したものをFILE_B.txtに出力するという処理です。 「!」マークの下行の文字列の「name」は共通です。 -------------------------------------------- 【FILE_A.txt】 ! name abcdeLV 123.123.123.123 123.123.123.124 123.123.123.125 ! name fghijLV 10.10.10.11 10.10.10.12 10.10.10.13 10.10.10.15 10.10.10.16 ! -------------------------------------------- ↓ -------------------------------------------- 【FILE_B.txt】 123.123.123.123 abcdeLV 123.123.123.124 abcdeLV 123.123.123.125 abcdeLV 10.10.10.11 fghijLV 10.10.10.12 fghijLV 10.10.10.13 10.10.10.15 fghijLV 10.10.10.16 fghijLV -------------------------------------------- 上記のようなPerlでの処理を具体的に教えて頂ければうれしいです。 本サイトのようなものを利用するのが初めてですので、不手際があるかもしれませんが なにとぞよろしくお願いいたします。

    • ベストアンサー
    • Perl

専門家に質問してみよう