プロが教える店舗&オフィスのセキュリティ対策術

プログラム初心者です。
よろしくお願いします。

下記のように項目分けされたデータがあります。
--
【項目1】あいうえお
【項目2】かきくけこ
【項目3】さしすせそ
【項目4】
123456789
【項目5】
987654321A
012345678B
【項目6】たちつてと
【項目7】なにぬねの
--
このデータの中から【項目2】、【項目4】、【項目5】データを抽出したいのですが、うまくいきません。
つまり、下記のように抽出したいのです。
--
【項目2】かきくけこ
【項目4】
123456789
【項目5】
987654321A
012345678B
--

現在は、
while(<STDIN>)でファイルを行ごとに読み込みまして
if(/【項目2】/){
print ;
}
if(/【項目4】/){
print ;
}
if(/【項目5】/){
print ;
}
としているのですが、これでは改行されいる項目4と項目5の内容部分が抽出できません。
このデータも取り出すためには、どのようにすれば良いのでしょうか?

PERLを始めて1週間でして、簡単なことかもしれませんが、ご教授ください。
よろしくお願いします。

A 回答 (2件)

1行ずつ読み込んで判断・処理するのではなく、先に読み込んで項目ごとにデータをまとめてから処理するとよいと思います。


例えばこんな感じ。

# 項目ごとにデータをまとめる配列を用意
@data = ();

# 読み込みながら、項目ごとにまとめる
while (<STDIN>) {
  # 項目名の行なら、新しいデータとして @data に追加
  if (/^【項目.+】/) { push @data, $_ }
  # 違うなら、@data の最後のデータに連結
  else { $data[-1] .= $_ }
}

これで項目1~7が $data[0]~$data[6] に入るので、
print $data[3];
とすれば
【項目4】
123456789
と表示されます。

※スクリプトをコピーする場合は、全角スペースをタブなどに置換して下さい。
    • good
    • 0
この回答へのお礼

ありがとうございます。

配列を使うと良いのですね。参考になりました。
私の質問の仕方が悪く、大変恐縮なのですが、
ファイルは複数ありまして、データ内の項目数もファイルによって違いがあります。重なる項目もあります。

そのため、print $data[3];としてもファイルによって抽出される項目が違ってきます。
ただし、抽出する項目は、全ファイル同様です。

できましたら、【項目2】、【項目4】、【項目5】という抽出したい項目のみを配列に入れまして、全ファイルとも同様の項目で出力したいと考えています。

よろしくご教授ください。

お礼日時:2004/10/26 18:10

なるほど、項目名で抽出する必要があったのですね。


でしたら配列の変わりにハッシュを利用すると良さそうです。

%data = ();
$key = "";
while (<STDIN>) {
  if (/^(【項目.+?】)/) { $data{$key=$1} = $_ }
  else { $data{$key} .= $_ }
}

このようにすると、print $data{"【項目4】"} のように使うことができます。
※この例では項目名をそのままハッシュのキーにしましたが、項目番号だけを取り出してキーにしても構いません。
※else 部で最後の要素にデータを連結する際、配列では $data[-1] で最後尾にアクセスできましたが、ハッシュではそのような手段がないので、最後に追加したキーを変数($key)で覚えておくようにしています。

なお、複数のファイルがあるということなので、ファイルオープンなども含めて関数化してしまうとよいでしょう。

sub read_item_file {
  my ($file_name) = @_;
  my (%data, $key);
  open FH, $file_name or die "$file_name:$!";
  while (<FH>) {
    if (/^(【項目.+?】)/) { $data{$key=$1} = $_ }
    else { $data{$key} .= $_ }
  }
  close FH;
  return \%data;
}

# 利用例
my @item_list;
push @item_list, read_item_file("item1.dat");
push @item_list, read_item_file("item2.dat");
   :

foreach my $data (@item_list) {
  print $data->{"【項目4】"}, "\n";
}
    • good
    • 0
この回答へのお礼

返信が遅くなり申し訳ありません。
いろいろと試してみまして、ハッシュを使った方法が一番うまくいきそうです。

ありがとうございました。

お礼日時:2004/10/31 18:50

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