プログラム初心者なので、あまりうまく説明できませんが、よろしくお願いします。
あるテキストデータから、一部分だけをだけを取り出したいのです。
例えば、

例1
 ■見出し1■
  ・データ1
  ・データ1
 ■見出し2■
  ・データ2
  ・データ2
 ■見出し3■
  ・データ3
  ・データ3
のようなデータから、■見出し2■とその中にある内容(・データ2の内容は
いくつもあるものとする)でだけを取り出したいのですが、どうすれば
よいのでしょうか?■見出し*■をkeyとしてハッシュに入れて、複数個
の値をつればようのでしょうか?
それとも、他の方法で処理したほうがよいのでしょうか?
文字列から文字列までの指定というのは、どうすればよいのでしょうか?

回答よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (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;
}

この回答への補足

返答が遅くなってしまって申し訳ありません。
丁重な説明をして頂き、誠にありがとうございました。

 今回、私がやりたい事は、多くの情報の中から、知りたい情報だけをを抜きだしてきて、それを携帯電話などのモバイル機器でも見やすくするように、編集できないかと考えています。

 例えば学校などのHPなどで連絡事項のページがあったとすると、その大きな連絡事項群の中から、例えば、「休講情報」について知りたいとします。
それを、携帯でも情報を見やすくするために、余計なものを取り除いて、「休講情報」だけの、新しい容量の小さいwebページを作りたいのです。
ここで、情報源となるHTMLページには、休講情報の内容の数や範囲などは、こちらでは全く指定できません。

 そのための処理をしたいのですがどうもうまくいきませんでした。タブと余計なスペースなどを削除することはできたのですが(本に書いてあった通りに書いただけですけど)、この1番メインとなる処理がうまくいきませんでした。

そこで、読み込んだデータから、部分的な抜き出し方法が知りたかったのです。

キーとなるものも、もしかしたら変化するかも知れませんし、その中の内容は、
もちろん変わってしまうと考えられます。扱いずらいデータですよね。。。。

先日、例としてあげたデータのように、どこかマークの間にはさまれている文字が
見出しとなっており、その後に書かれているものが内容だということは、変わらな
いと思います。

もし、このようなデータを処理するのに良い方法がありましたら、御教授お願いいたします。

補足日時:2002/01/09 06:51
    • good
    • 0
この回答へのお礼

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

お礼日時:2002/01/15 01:16

今一つ質問の内容が理解できていないのですが,一応「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(もちろん許可は頂いてあります)から欲しいデータだけを取り出したいのです。

そのための処理を行うのには、どうすれば効率が良いかなどを、もう一度よろしければ、お力を借りたいと思います。
あつかましいのですが、よろしくお願いいたします。

補足日時:2002/01/09 07:06
    • good
    • 0
この回答へのお礼

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

お礼日時:2002/01/15 01:29

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q動画の読み込み速度を上げる方法ってありませんか?

現在動画読み込み速度は1秒約100KB(800kbps)です

ファイルやゲームのダウンロードの速度は一秒570~620KB(4.5MB~4.9MB)
プロバイダで契約しているのは5Mbpsです。

なぜ動画の方が遅くなるのでしょうか?
動画がカクカクして見にくいです。(画質を下げろっていう回答はやめてください)
ダウンロード中でもありません。

メモリは8GB
GPUは内臓のでintel HD Graphics3000 を使っています。
CPUはintel corei7 第二世代のを使っています。
OSはwin8.1です。
HDDは750GBあって50GBしかつかってません。

最適化もしました。ブラウザのキャッシュクリアもしました。

Aベストアンサー

驚きの事実 : 相手の送ってくれる以上のモノは受け取れません。

>なぜ動画読み込みのほうが遅いのでしょうか?

動画サイトのサーバーの送り出し速度は1秒約100KB(800kbps)
ファイルサーバーやゲームサーバーの ア ッ プ ロ ー ド の速度は一秒570~620KB(4.5MB~4.9MB)

動画サイトのサーバーの方がそもそも能力が低いか、そのとき混雑していたのでしょう。

自宅--回線--プロバイダ--(インターネット)--各種サーバー
質問者は自分の側の事情しか考えたことないようですが、通信ってのは「相手」の存在するものです。
インターネットの向こう側にあるサーバーの能力・混雑具合はまちまちです。

有料・無料で区別しているところなら、お金払うといいでしょう。

参考URL:https://secure.nicovideo.jp/secure/register?from=header

Qハッシュのハッシュの値代入で悩んでいます

2次元風配列$yaoya_array[$i][$j]から、ハッシュのハッシュ%yaoyaを作成しようとしています。
$yaoya_array[$i][$j]の[$j]の部分は、添え字によって、以下のようなデータを表します。また、NULLの場合もあるとします。

#--- $yaoya_array の中身
$yaoya_array[$i][0] 品物の名前
$yaoya_array[$i][1] 品物の個数
$yaoya_array[$i][2] 品物の値段

上記のデータがダブりもありで、下のように複数個存在します。

#--- $yaoya_array の中身
$yaoya_array[0][0] = 'みかん';
$yaoya_array[0][1] = 3;
$yaoya_array[0][2] = '';
$yaoya_array[1][0] = 'みかん'
$yaoya_array[1][1] = '';
$yaoya_array[1][2] = 300;

上記のデータから、下記のようなハッシュのハッシュ%yaoyaを作成しようとしています。要するに、ばらばらに存在する品物のデータをまとめようとしています。

%yaoya = ('みかん' => {'個数' => 3, '値段' =>300});

そこで、下記のようにしてみたのですが、forループが終わった時には、'kosuu'に何も入っていません。具体的には、1回目のループで'kosuu'=>3、'nedan'=>""になり、2回目のループで'kosuu'=>""、'nedan'=>300となってしまい、'kosuu'=>3が保存されていないみたいです。ifでNULLの場合は値を代入しないようにしているつもりなのですが…。
ループ終了時に'kosuu'=>3、'nedan'=>300となるようにするには、どうすればよいのでしょうか?

#-- %yaoya の作成
for my $i( 0 .. $#yaoya_array ){
if( $yaoya_array[$i][1] ne "" ){
%yaoya = ( $yaoya_array[0] => {'kosuu' => $yaoya_array[$i][1]} );
}
if( $yaoya_array[$i][2] ne "" ){
%yaoya = ( $yaoya_array[0] => {'nedan' => $yaoya_array[$i][2]} );
}
}

2次元風配列$yaoya_array[$i][$j]から、ハッシュのハッシュ%yaoyaを作成しようとしています。
$yaoya_array[$i][$j]の[$j]の部分は、添え字によって、以下のようなデータを表します。また、NULLの場合もあるとします。

#--- $yaoya_array の中身
$yaoya_array[$i][0] 品物の名前
$yaoya_array[$i][1] 品物の個数
$yaoya_array[$i][2] 品物の値段

上記のデータがダブりもありで、下のように複数個存在します。

#--- $yaoya_array の中身
$yaoya_array[0][0] = 'みかん';
$yaoya_array[0][1] = 3...続きを読む

Aベストアンサー

動作確認済み

use Data::Dumper;

#--- $yaoya_array の中身
$yaoya_array[0][0] = 'みかん';
$yaoya_array[0][1] = 3;
$yaoya_array[0][2] = '';
$yaoya_array[1][0] = 'みかん';
$yaoya_array[1][1] = '';
$yaoya_array[1][2] = 300;

#-- %yaoya の作成
for my $i( 0 .. $#yaoya_array ){
if( $yaoya_array[$i][1] ne "" ){
$yaoya{$yaoya_array[$i][0]}->{'kosuu'} = $yaoya_array[$i][1];
}
if( $yaoya_array[$i][2] ne "" ){
$yaoya{$yaoya_array[$i][0]}->{'nedan'} = $yaoya_array[$i][2];
}
}
#%yaoya = ('みかん' => {'個数' => 3, '値段' =>300});
print Dumper(\%yaoya);

動作確認済み

use Data::Dumper;

#--- $yaoya_array の中身
$yaoya_array[0][0] = 'みかん';
$yaoya_array[0][1] = 3;
$yaoya_array[0][2] = '';
$yaoya_array[1][0] = 'みかん';
$yaoya_array[1][1] = '';
$yaoya_array[1][2] = 300;

#-- %yaoya の作成
for my $i( 0 .. $#yaoya_array ){
if( $yaoya_array[$i][1] ne "" ){
$yaoya{$yaoya_array[$i][0]}->{'kosuu'} = $yaoya_array[$i][1];
}
if( $yaoya_array[$i][2] ne "" ){
$yaoya{$yaoya_array[$i][0]}->{'nedan'} = $yaoya_array[$i]...続きを読む

Qファイル読み込み/書き込み速度を上げるには

下記のようなファイルの読み込み/書き込み処理において、もっと効率よく(速く)読み込み・書き込みをしたい場合どのような工夫をすれば良いでしょうか?

BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("sample2.data"));
BufferedInputStream in = new BufferedInputStream(new FileInputStream("sample1.data"));
int c ;
while((c = in.read()) != -1)
{
out.write(c);
}
in.close();
out.flush();
out.close();

Aベストアンサー

速くなるかどうかは環境によって微妙に違うと思いますが、効率よくやる方法が2つあります。

1. 1バイトづつ読み書きするのではなくて byte[] で1000バイトとかの塊を読んでそのまま塊を書くようにする。(こうすると read, write をする回数が減るので少し速いと思います)。

2. FileInputStream と FileOutputStream のインスタンス双方から getChannel() で java.nio.channels.FileChannel のインスタンスを取り出し、FileOutputStream 側から取り出した FileChannel のインスタンスに対して transferFrom() で FileInputStream 側から取り出した FileChannel のインスタンスを指定する。

例) in は FileInputStream のインスタンス, out が FileOutputStream のインスタンスの場合。

FileChannel fcin = in.getChannel(), fcout = out.getChannel();
fcout.transferFrom(fcin, 0, fcin.size());

速くなるかどうかは環境によって微妙に違うと思いますが、効率よくやる方法が2つあります。

1. 1バイトづつ読み書きするのではなくて byte[] で1000バイトとかの塊を読んでそのまま塊を書くようにする。(こうすると read, write をする回数が減るので少し速いと思います)。

2. FileInputStream と FileOutputStream のインスタンス双方から getChannel() で java.nio.channels.FileChannel のインスタンスを取り出し、FileOutputStream 側から取り出した FileChannel のインスタンスに対して transferFrom()...続きを読む

Qハッシュのハッシュを実現したい。

ハッシュのハッシュを行いたいですがうまくいきません。

◆正しい例

%ultraman = (
TARO => { cpu => "Celeron(266MHz)",
memory=> "32MB",
hdd => "4.3GB",
},
JACK => { cpu => "Pentium2(333Mhz*2)",
memory=> "128MB",
hdd => "9GB*4",
},
);

$name = "JACK";
$item = "cpu";
print "\$ultraman{$name}{$item}=[$ultraman{$name}{$item}]";
exit(0);
__END__


◆このように使えたら便利(要はハッシュの代入でハッシュのハッシュを実現したい)

%a=();
%b = ("cpu"=>"aaaa", "memory"=>"bbbb");
$a{'JACK'} = %b; #---> このように代入したい
$name = "JACK";
$item = "cpu";
print "\$a{$name}{$item}=[$a{$name}{$item}]";
exit(0);
__END__

ハッシュのハッシュを行いたいですがうまくいきません。

◆正しい例

%ultraman = (
TARO => { cpu => "Celeron(266MHz)",
memory=> "32MB",
hdd => "4.3GB",
},
JACK => { cpu => "Pentium2(333Mhz*2)",
memory=> "128MB",
hdd => "9GB*4",
},
);

$name = "JACK";
$item = "cpu";
print "\$ultraman{$name}{$item}=[$ultraman{$name}{$item}]";
exit(0);
__END__


◆このように使えた...続きを読む

Aベストアンサー

$hash{'key'} = %value;

のように、ハッシュの値としてハッシュを代入すること
はできません。コンパイルは通りますが意味不明の結果
となります。

ハッシュの値として使えるのはスカラーです。
従いまして、ハッシュのハッシュを実現するためには
リファレンスを使う必要があります。リファレンスは
スカラーの一種です。

メソッド1
$hash{'key'} = \%value;

メソッド2
$hash{'key'} = {'key' => 'value'};

メソッド3
$value_hash = {'key' => 'value'};
$hash{'key'} = $value_hash;

ご参考になれば幸いです。

Qプレステ2の読み込み速度について

SCPH-15000→SCPH-79000(90000)は、SONYによると読み込み速度は変わらないとの返答を得たのですが、読み込み速度が速いという噂も聞きました。実際のところどうなのでしょうか?

Aベストアンサー

そうですね。若干早いような気がしますね。基本的にどんどん高性能になってきていますから、読み込み速度、処理能力などよくなってるはずですよ。

Q投票データをハッシュを使用して入出力する

こんにちは。tyabudaiと申します。

アンケート(投票)のCGIを
作成しようと思っています。

ログの中身は、(とりあえずカンマ区切りで)
「項目,数値」です。
処理のイメージとしては、
まずログファイルの内容を、
「項目」をキーとしたハッシュに取り込みます。
投票があった場合、
「項目」をキーとして「数値」を取り出し、
1つ増加させる処理をしたいです。

現在、他サイト様よりCGIをダウンロードして
そのような処理がないか探していますが、
全く手がかりがありません。

まずは、ログファイルの内容をハッシュに取り込む方法を
お教えいただけないでしょうか。

ご存知の方のお力添えいただければ幸いです。

Aベストアンサー

> foreach (%hash)
> {
> print << "END";
> $key は $hash{$key}
> <BR>
> END
> }
ここが違います。正しくはこうなります。
foreach (keys %hash)
{
print << "END";
$_ は $hash{$_}
<BR>
END
}

なぜ最後のデータが表示されるのかというと、
> $key は $hash{$key}
での $key には、
> while(<IN>) {
> ($key,$val)=split(/,/,$_);
> $hash{$key}=$val;
> }
で最後に参照した「ううう」が入っているため、毎回 $hash{'ううう'} が表示されるからです。
また、なぜ6回表示されるのかというと、これは %hash を
> foreach (%hash)
で、リストとして評価しているため、('あああ',2,'いいい',5,'ううう',10)というリストの要素の数(6個)分だけループするからです。

foreach やハッシュについての詳しい使い方などについては、参考書などを読んでみて下さい。

> foreach (%hash)
> {
> print << "END";
> $key は $hash{$key}
> <BR>
> END
> }
ここが違います。正しくはこうなります。
foreach (keys %hash)
{
print << "END";
$_ は $hash{$_}
<BR>
END
}

なぜ最後のデータが表示されるのかというと、
> $key は $hash{$key}
での $key には、
> while(<IN>) {
> ($key,$val)=split(/,/,$_);
> $hash{$key}=$val;
> }
で最後に参照した「ううう」が入っているため、毎回 $hash{'ううう'} が表示されるからです。
また、なぜ...続きを読む

Qパソコンのドライブを購入したのですが、安いためか最大読み込み速度と書き込み速度がCD-Rで24xと記

パソコンのドライブを購入したのですが、安いためか最大読み込み速度と書き込み速度がCD-Rで24xと記載してありました。しかし、自分は48x対応のCDをパソコンにコピーしたいのです。このドライブに自分が持っているCDを挿入しても非対応なのでしょうか?それとも、読み込み速度が遅いだけで、一応対応するのでしょうか?

Aベストアンサー

>読み込み速度が遅いだけで、一応対応するのでしょうか?

結論は、問題なく対応します。
そもそも
>自分は48x対応のCDをパソコンにコピーしたいのです。

読み込みが48x 対応のCDなんて存在しません。
CDの読み込み速度は、乱暴な言い方をすると無限大で、
使用するドライブによって、x倍速の制限がかかります。
48x 対応などの表示は書き込み速度の表示です。

Q文字列データからある部分のみデータ取得

いつもお世話になっております。
Perlは初心者です。

例えば下記のような内容のデータから
"6月1日(木)"と "午後6時30分~午後7時30分"
のみのデータを取得したいのですが・・

<tr valign="top">
<td class="td1">6月1日(木)</td><td class="td1">午後6時30分~午後7時30分</td>
</tr>


正規表現で簡単に表せそうなのですが、
うまく出来ません。

よろしくお願い致します。

Aベストアンサー

$_に1行格納されているとして、
@word = ($_ =~ />([^<]+)</g);
で、うまくいきそうな気がします。
格納されている個数は@#word、$word[0]、$word[1]・・・に中身が入ります。

Q新旧2台のPCでDVD Decrypterの読み込み速度が違うのはナゼ??

新旧2台のPCがあるのですが…
DVDをDVD Decrypterで読み込まして見ると読み込み速度が3倍ぐらい違います。
しかもスペックが劣る旧型のPCの方が新PCより早いのです。

●旧型 WindowsXP SP2
    Pentium4 3.2G
ドライブ GSA-4163B
DVD-DL 読み込み 2.4X~4X

●新型 WindowsXP SP3
    Quad Q6600 2.4G
ドライブ LH-20A1P
DVD-DL 読み込み 不明

多分、ReadSpeedもLH-20A1Pの方が早いかと…。
DVD Decrypterの設定も両PC共に「デバイス」の「オプション」の読み込み速度を「最大」に設定しています。

こういった環境でDVD-DLを読み込ませると旧型は20分ほどで、
新型は1時間ぐらいかかってしまいます。

これは何故でしょうか??

Aベストアンサー

アプリケーション・プログラム(DVD Decryter)が、

マルチスレッド対応プログラムでないからです。

Qフォームデータをハッシュで返すには?

前画面の入力内容を&ReadParse()を用いて取得し、
その後テキストボックス名などのオブジェクト名と
入力内容をEUCに変換してハッシュで返すという
サブルーチンを作っています。
サブルーチンなので不特定多数の画面から呼び出されます。
下記のとおりにしてみたのですが、うまくハッシュに入っていないらしく、値を取得することができません。
どのようにすればいいでしょうか?

----以下プログラム----
sub Comp_SetParam {
&ReadParse(*form);# パラメータ受取

#引数として渡されたフォームデータを格納
while(($key,$val) = each(%form)){
 #キー名(画面のオブジェクト名)をEUC変換
 &jcode::convert(*key ,'euc');

 #画面入力値をEUC変換
 &jcode::convert(*val ,'euc');

 %in = ("$key" => "$val");

}

#ハッシュにし返す
 return %in;
}

前画面の入力内容を&ReadParse()を用いて取得し、
その後テキストボックス名などのオブジェクト名と
入力内容をEUCに変換してハッシュで返すという
サブルーチンを作っています。
サブルーチンなので不特定多数の画面から呼び出されます。
下記のとおりにしてみたのですが、うまくハッシュに入っていないらしく、値を取得することができません。
どのようにすればいいでしょうか?

----以下プログラム----
sub Comp_SetParam {
&ReadParse(*form);# パラメータ受取

#引数として渡されたフォームデー...続きを読む

Aベストアンサー

%in = ("$key" => "$val");
じゃなくって
$in{$key} = $val;
だと思いますが....

while の前に
%in = ();
が必要ですけどね.


人気Q&Aランキング

おすすめ情報