• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:perlでご助言お願い致します。)

perlでテキストファイルの処理方法について

このQ&Aのポイント
  • perlでテキストファイルの処理方法についてアドバイスをいただきたいです。
  • テキストファイル内のデータを1列目と2列目の関係性を確認するperlプログラムを作成したいです。
  • 具体的には、一行ずつ読み込んで1列目と2列目をマッチさせる方法についてです。

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

  • ベストアンサー
  • root139
  • ベストアンサー率60% (488/809)
回答No.3

> file名が一度変わり、さらに変わるときに既に出てきたfile名はエラーとする です。 同じfile名の行はひとかたまりに成っていなくてはダメということでしょうか? であるなら、生成する部分で「直前のfile名と違い、かつ、既に出現済のfile名を取得した」場合にエラーにすれば良いでしょう。 例) ---------------------------------------------- my $previousFile = ''; while (<FILE>) { if ($_ =~ /(\S+)\s+(\S+)/) { if ($previousFile and $2 ne $previousFile and exists($data{$2})) { die "$2は既に出てきたためエラーとして処理をストップしました"; } $data{$2}{$1} = 1; $previousFile = $2; } } -------------------------------------------------- > これをループ文(whileやforeach)などで取り出す場合の記述例を御教授願います。 %result のキーでループさせてその内側で値の配列をループさせれば全要素を走査できます。file名順に並べなくても良いなら while と each の組合せでも大丈夫です。 例) ---------------------------------------------- foreach my $file (sort(keys(%result))) { print "* $file\n"; foreach my $str (@{$result{$file}}) { print " - $str\n"; } } -------------------------------------------------- 単に配列が値になっているハッシュというだけの話なので、perlの制御構文やハッシュの使い方を調べれば、走査のやり方は分かるでしょう。 http://rfs.jp/sb/perl/02/06.html http://rfs.jp/sb/perl/02/05.html なお、ベストアンサーはどうでも良いですが、マルチポストは止めましょう。いちおう、このサイトのルールですし、質問する方も回答する方も面倒なだけでしょう。

torajiro123
質問者

補足

マルチポストの件了解しました。 返信遅くなってしまい大変失礼致しました。 助かりました。ありがとうございました。

その他の回答 (2)

  • root139
  • ベストアンサー率60% (488/809)
回答No.2

> $data{$2} = 値 のようにキーは$2のみにして$1は値として 一度ハッシュのハッシュを作った上で、それから配列のハッシュを作るのが簡単でしょう。 例) ---------------------------------------------- my %data = (); open(FILE, 'hoge.txt') or die "file open failed."; while(<FILE>) { if ( $_ =~ /(\S+)\s+(\S+)/ ) { $data{$2}{$1} = 1; } } close(FILE); # 配列のハッシュを作る my %result = (); while(my ($key, $val) = each(%data)) { $result{$key} = [sort(keys(%$val))]; } # 生成したデータ表示してみる。 foreach my $file (sort(keys(%result))) { print $file . " -> " . join(',', @{$result{$file}}) . "\n"; } use Data::Dumper; print Dumper(\%result); -------------------------------------------------- 1ループでも出来ない事はないですが、かえって面倒だと思いますよ。 > また出力はただのprintでお願いできますか。 えーと、データ表示の部分に関しては、実行した際にデータがどの様に格納されているのか確認できるように付けただけですので、コード自体の意味が分からなかったら無視して頂いても大丈夫です。

torajiro123
質問者

補足

root139様 御回答ありがとうございます。 すでにベストアンサーに決定することを決めています。 しかし、もう2点の課題について御教授いただければと思います。 (この課題がわからなくて答えられなくてもベストアンサーにするのでご安心を) 1点目です。 テキストファイルの続きが存在し、 g  file1 g  file1 g  file1 のような続き行があるとします。 file1は既に出てきた値としてエラー文 「file1は既に出てきたためエラーとして処理をストップしました」 を出力させたいのです。 エラーの条件は、file列でfile1→file2→file1のように file名が一度変わり、さらに変わるときに既に出てきたfile名 はエラーとする です。 具体的に言いますと新しい行をテキストファイルに追加する場合、 2列目は file1 file2 以外のfile名でなくてはなりません(file3は許されます) 2点目 while(my ($key, $val) = each(%data)) {  $result{$key} = [sort(keys(%$val))]; } の%resultに格納された配列を実際に取り出したい 場合の取り出し方のバリエーションを記述お願いできますでしょうか。 $result{$key}[0] で1列目の1個目の要素を取り出せそうに思えますが、 これをループ文(whileやforeach)などで 取り出す場合の記述例を御教授願います。 長々となってしまい申し訳ございませんが、宜しくお願い致します。

  • root139
  • ベストアンサー率60% (488/809)
回答No.1

やり方はいろいろ有ると思いますが、ハッシュのハッシュを使うのが簡単だろうと思います。 例) ---------------------------------------------- my %data = (); open(FILE, 'hoge.txt') or die "file open error!."; while(<FILE>) { if ( $_ =~ /(\S+)\s+(\S+)/ ) { $data{$2}{$1} = 1; } } close(FILE); # 生成したデータ表示してみる。 foreach my $file (sort(keys(%data))) { printf("%s -> %s\n", $file, join(',', sort(keys(%{$data{$file}})))); } use Data::Dumper; print Dumper(\%data); -------------------------------------------------- 生成しているデータは、最後の Data::Dumper の出力を見てもらえば分かりますが、1列目の[a, b, c]がキーで値が1のハッシュを2列目のfile名がキーのハッシュに格納しています。

torajiro123
質問者

補足

ご回答ありがとうございます。 また補足ですみません。 ハッシュの値は1ではなく、 $data{$2} = 値 のようにキーは$2のみにして$1は値として 格納することを考えてますので、そういった 場合どう記述すればいいのか宜しくお願い致します。 また出力はただのprintでお願いできますか。 自分まだまだ初心者なものでして、 printfやdumperがわかりません。 普通のprintならわかります。 宜しくお願い致します。