- ベストアンサー
Perlによる文字の抽出方法
プログラム初心者なので、あまりうまく説明できませんが、よろしくお願いします。 あるテキストデータから、一部分だけをだけを取り出したいのです。 例えば、 例1 ■見出し1■ ・データ1 ・データ1 ■見出し2■ ・データ2 ・データ2 ■見出し3■ ・データ3 ・データ3 のようなデータから、■見出し2■とその中にある内容(・データ2の内容は いくつもあるものとする)でだけを取り出したいのですが、どうすれば よいのでしょうか?■見出し*■をkeyとしてハッシュに入れて、複数個 の値をつればようのでしょうか? それとも、他の方法で処理したほうがよいのでしょうか? 文字列から文字列までの指定というのは、どうすればよいのでしょうか? 回答よろしくお願いします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
むちゃくちゃ長くて申し訳ありません。 回答しようとしてみて、いろいろなことが気になってしまって長くなりました。 間違いはないように努力していますが、もっといい解決方法はあるかも知れません。 ハッシュのキーは、重複が許されません。 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; }
その他の回答 (1)
- aton
- ベストアンサー率47% (160/334)
今一つ質問の内容が理解できていないのですが,一応「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); ... これをループで回すなり何なりして処理すればできると思います。
お礼
ありがとうございました(^^)
補足
回答ありがとうございました。 前回、私の問題に対する質問が曖昧だったので今回は、具体的に行いたかった処理補足させていただいきます。 No.1の回答者の方のところにも補足させていただいたので詳しい内容は、省略させていただきますが、他人が作ったHP(もちろん許可は頂いてあります)から欲しいデータだけを取り出したいのです。 そのための処理を行うのには、どうすれば効率が良いかなどを、もう一度よろしければ、お力を借りたいと思います。 あつかましいのですが、よろしくお願いいたします。
お礼
ありがとうございました。 解決することができました(^^)
補足
返答が遅くなってしまって申し訳ありません。 丁重な説明をして頂き、誠にありがとうございました。 今回、私がやりたい事は、多くの情報の中から、知りたい情報だけをを抜きだしてきて、それを携帯電話などのモバイル機器でも見やすくするように、編集できないかと考えています。 例えば学校などのHPなどで連絡事項のページがあったとすると、その大きな連絡事項群の中から、例えば、「休講情報」について知りたいとします。 それを、携帯でも情報を見やすくするために、余計なものを取り除いて、「休講情報」だけの、新しい容量の小さいwebページを作りたいのです。 ここで、情報源となるHTMLページには、休講情報の内容の数や範囲などは、こちらでは全く指定できません。 そのための処理をしたいのですがどうもうまくいきませんでした。タブと余計なスペースなどを削除することはできたのですが(本に書いてあった通りに書いただけですけど)、この1番メインとなる処理がうまくいきませんでした。 そこで、読み込んだデータから、部分的な抜き出し方法が知りたかったのです。 キーとなるものも、もしかしたら変化するかも知れませんし、その中の内容は、 もちろん変わってしまうと考えられます。扱いずらいデータですよね。。。。 先日、例としてあげたデータのように、どこかマークの間にはさまれている文字が 見出しとなっており、その後に書かれているものが内容だということは、変わらな いと思います。 もし、このようなデータを処理するのに良い方法がありましたら、御教授お願いいたします。