二次元配列への格納|ファイル名:log.datのデータを二次元配列に変換する方法

このQ&Aのポイント
  • log.datというファイルに格納されているデータを読み込んで、二次元配列に変換する方法を解説します。
  • データの読み込み後、空白や改行、二重引用符を取り除き、パイプ記号で区切られた要素を二次元配列に格納します。
  • これにより、log.datのデータが二次元配列​​として取得できます。
回答を見る
  • ベストアンサー

二次元配列への格納

ファイル名:log.dat は以下の構造をしています。 "Key-01"|"参照"|"P2"|"yamada" (\n\r)←改行 "Key-02"|"書込"|"P5"|"minami" (\n\r)←改行 "Key-03"|"参照"|"P3"|"yamada" (\n\r)←改行 open(IN,"log.dat") || die "log.dat",": $!"; @log=<IN>; close(IN); で@logにデータを読み込んだ後、 foreach(@log){ $data = $_; $data =~ s/ //g; $data =~ s/\n//g; $data =~ s/\r//g; $data =~ s/"//g; @second =split(/\|/ , $data); <---(1) で配列@secondに格納するのですが、 この時、@secondを(\n\r)=改行で区切るように二次元配列にしたい のです。 @second = ( [ Key-01 , 参照 , P2 , yamada ] [ Key-02 , 書込 , P5 , minami ] [ Key-03 , 参照 , P3 , yamada ] ) 上記<---(1) の部分をどのように変更すればいいでしょうか。

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

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

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

split の結果を配列のリファレンスにしてやって、 @secondにpushすればいいです。 こんな感じで。 ところで改行は \r\n ではなくて \n\rなんですか? use strict; use warnings; use Data::Dumper; my @second; open my $fh, '<', 'log.dat' or die "log.dat",": $!"; foreach my $line (<$fh>) { #chomp $line; $line =~ tr /" \n\r//d; push @second, [split /[|]/, $line]; } close $fh; print Dumper @second;

myfrend
質問者

お礼

どうも回答ありがとうございました。

その他の回答 (1)

  • guci-ok
  • ベストアンサー率33% (49/146)
回答No.2

No.1でいいんですが、 File::Slurpをつかうとプログラムがすっきりします。 それと、Data::Dumpのほうか表示がすっきりしています。 #!Perl use strict; use File::Slurp; use Data::Dump qw(dump); my @log = read_file("log.dat"); my @second; for (@log) { chomp; my @data = split /\|/; s/(^"|"$)//g for @data; push @second => \@data; } print dump(\@second); __END__

myfrend
質問者

お礼

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

関連するQ&A

  • 多次元配列の初期化

    多次元配列の初期化を行いたいのですが、 下記の方法では、配列の値が多くなったときに大変 なので他に良い方法はありませんでしょうか? char lesson[7][6] = { {'A', 'B', 'C', 'D', 'E', 'F'}, {'G', 'H', 'I', 'J', 'K', 'L'}, {'M', 'N', 'O', 'P', 'Q', 'R'}, {'S', 'T', 'U', 'V', 'W', 'X'}, {'Y', 'Z', 'a', 'b', 'c', 'd'}, {'e', 'f', 'g', 'h', 'i', 'j'}, {'k', 'l', 'm', 'n', 'o', 'p'}, };

  • 別のファイルにあるレコードを各配列に格納したいです

    ファイル"DATA.dat"にあるレコードを配列"Record"にそれぞれ格納するプログラム考えてみましたが、なかなか動いてくれません。何かアドバイスをください。 DATA.datの内容 0001 0010 0011 0100 0101 : : Record配列にレコードを格納するイメージ Record[0] <- 0001 Record[1] <- 0010 Record[2] <- 0011 Record[3] <- 0100 Record[4] <- 0101     :     : 考えたプログラム #include <stdio.h> #include <stdlib.h> void main() { FILE *File_pt; char Record[100]; int i; //TimeLineファイルをOpenする if ( (File_pt = fopen("DATA.dat", "r")) != NULL){ for(i = 0 ; i < 5 ; i++){ if( (fscanf(File_pt, "%s", Record[i])) == EOF){ printf("各レコード格納失敗\n"); exit(1); } } //////格納されたレコードを表示する for(i = 0 ; i < 5 ; i++){ printf("%s\n",Record[i]); } fclose(File_pt); }else{ printf("失敗\n"); exit(1); } } まだ初心者なんでおねがいします。

  • 改行の変換がうまく出来ていない?

    perlの更新記録CGIを改造中です。 テキストエリアを数個設置しているのですが、うまく保存が出来ません。 新規情報を入力するときはちゃんと改行したいデータも保存されます。しかし、修正画面で、何もしないでそのまま保存し直したところ、変に改行が入ってしまいます。(情報の途中で改行が入るので、ゴミレコードが増えてしまう。) 修正画面からログに書き込む手前で<BR>の変換をしていますが、何が間違っているのでしょうか? $in{'kouc1'} =~ s/\r\n/<br>/g; $in{'kouc1'} =~ s/\r/<br>/g; $in{'kouc1'} =~ s/\n/<br>/g; $in{'kouc2'} =~ s/\r\n/<br>/g; $in{'kouc2'} =~ s/\r/<br>/g; $in{'kouc2'} =~ s/\n/<br>/g; $in{'kouc3'} =~ s/\r\n/<br>/g; $in{'kouc3'} =~ s/\r/<br>/g; $in{'kouc3'} =~ s/\n/<br>/g; 新規入力のほうもまったく同じ状態ですが、こちらは正常に保存されます。 足りない情報があればすぐに指摘をお願いします。

    • 締切済み
    • CGI
  • テキストエリアの<br />を非表示にするには

    掲示板のようなCGIを利用し、入力フォームから送信された情報が保存されるプログラムを利用しています。 そのcgiファイルに記述されたコードに以下の記述があります。 sub decode { &ReadParse; while (($key,$val) = each %in) { if ($key !~ /upfile/ ) { &Jcode'convert(*val, "utf8", "", "z"); if ( $key !~ /label_name/ ) { $val =~ s/</&lt;/g; $val =~ s/>/&gt;/g; } $val =~ s/\r\n/<br>/g; $val =~ s/\r|\n/<br>/g; } $in{"$key"} = "$val"; } $_v = $in{"_v"}; $del_img = $in{"del_img"}; } この記述によりテキストエリアで改行された際に「<br>」に変換されると思うのですが、これを<br>から<br />に変えるため、 $val =~ s/\r\n/<br>/g; $val =~ s/\r|\n/<br>/g;を $val =~ s/\r\n/<br \/>/g; $val =~ s/\r|\n/<br \/>/g;と変えました。 これにより、保存される改行コードが<br>から<br />に変わったのですが、その情報を編集するため再度保存された情報の入力フォームを呼び出すと、 テキストエリアでは改行されず、改行場所に<br />と入力されてしまいます。 もとのコードではテキストエリア内の改行は<br>が表示されず、ちゃんと改行されていました。 そこで以下のように書き直してみたのですが、やはり状況は変わりません。 sub decode { &ReadParse; while (($key,$val) = each %in) { if ($key !~ /upfile/ ) { &Jcode'convert(*val, "utf8", "", "z"); if ( $key !~ /label_name/ ) { $val =~ s/</&lt;/g; $val =~ s/>/&gt;/g; $val =~ s/ / /g; } $val =~ s/\r\n/<br \/>/g; $val =~ s/\r|\n/<br \/>/g; } $in{"$key"} = "$val"; } $_v = $in{"_v"}; $del_img = $in{"del_img"}; } 改行コード<br>を<br />に変更し、保存された情報を呼び出してもテキストエリアで改行コード<br />は表示されることなく改行される記述方法を教えてください。 分かりにくい文章で申し訳ありませんがよろしくお願いします。

    • ベストアンサー
    • CGI
  • テキストエリアが複数あるときの改行変換方法

    CGIを改造中です。 ログに保存するとき改行(<BR>)を変換する必要があると思うのですが、 複数のテキストエリアがある場合はどのようにしたら良いのでしょうか? 現状 $in{'$com1'} =~ s/\r\n/<br>/g; $in{'$com1'} =~ s/\r/<br>/g; $in{'$com1'} =~ s/\n/<br>/g; $in{'$com2'} =~ s/\r\n/<br>/g; $in{'$com2'} =~ s/\r/<br>/g; $in{'$com2'} =~ s/\n/<br>/g; ~~ と言う風に書いていますが、うまく変換されていないようで、ログが崩れてしまっています。 どのように記述するのが良いのでしょうか?

  • 二次元配列が上手くいきません

    Sample.txt 2 2 10 01 php <?php $handle = fopen('sample.txt','r'); // ファイルを開いてファイルポインタを取得 $contents = fread( $handle, 1024 ); // ファイル内容を1024バイト分読み込んで変数に格納 fclose( $handle ); // ファイルを閉じてファイルポインタを破棄 $start_part=array_map("trim",explode("\n",$contents));//$start_partは初期画像の行の配列 改行を削除 $r = $start_part[0];//横サイズを読み込む $g = $start_part[1];//縦サイズを読み込む $start[][]=""; //g行r列の2次元配列を作成 start[x][y],end[x][y]; for($j=0;$j<$g;$j++){ for($i=0;$i<$r;$i++){ $start[$i][$j] = substr($start_part[2+$j],$i,1); } } print_r($start); ?> xamppでphpの勉強をしている初心者です。 理想では$start[0][0]=1 $start[0][1]=0 $start[1][0]=0 $start[1][1]=1となってほしいのですが、 Array ( [0] => Array ( [0] => ) ) としか表示されず困っています。どこを直せばよいのでしょうか。どこが良くないのでしょうか。 ご教授ください。よろしくお願いします。

    • 締切済み
    • PHP
  • 多次元配列の new

    多次元配列を new すると、どのような型のサイズの領域の配列が確保されるんでしょうか?たとえば、  int (*a)[2] = new int[3][2]; とすると、  1. 長さ2のintの配列へのポインタ型の長さ3の配列の領域が確保される のか、  2. int[3][2] すなわち、int が 6 つ分の領域が確保される のか。 今まで、「そりゃあ 2 の方だろう」と信じ込んであまり考えずにいたんですが、「コードの型形式からすると 1 の方の解釈でもいいよなぁ」と、ふと思ったものですから、質問させていただきました。 わたしの環境で調べてみると(配列用のハウスキーピング的な余分の領域とか、パディングなどは無視して)、確かに 1 の方なんですか、これで標準準拠なんでしょうかね?^^; XP Home Edition Ver.2002 SP2 cygwin v.1.0.2-1 GNU g++ v.4.1.1 ===== #include <iostream> #include <new> #include <cstdlib> struct A { char a; void *operator new(std::size_t s) { void *p = std::malloc(s); std::cout << "A::new(): " << p << '\t' << s << '\n'; return p; } void operator delete(void *p, std::size_t s) { std::cout << "A::delete(): " << p << '\t' << s << '\n'; if (p) std::free(p); } void *operator new[](std::size_t s) { void *p = std::malloc(s); std::cout << "A::new[](): " << p << '\t' << s << '\n'; return p; } void operator delete[](void *p, std::size_t s) { std::cout << "A::delete[](): " << p << '\t' << s << '\n'; if (p) std::free(p); } }; int main() { std::cout << sizeof(char) << '\t' << sizeof(A) << '\t' << sizeof(A(*)[8]) << '\n'; A *a = new A; std::cout << a << '\n'; A *aa = new A[8]; std::cout << aa << '\n'; A (*aaa)[8] = new A[8][8]; std::cout << aaa << '\n'; A (*aaaa)[8][8] = new A[8][8][8]; std::cout << aaaa << '\n'; delete[] aaaa; delete[] aaa; delete[] aa; delete a; } ===== % ./a.exe 1 1 4 A::new(): 0x870668 1 0x870668 A::new[](): 0x870678 12 0x87067c A::new[](): 0x870688 68 0x87068c A::new[](): 0x8706d0 516 0x8706d4 A::delete[](): 0x8706d0 516 A::delete[](): 0x870688 68 A::delete[](): 0x870678 12 A::delete(): 0x870668 1

  • 改行<br>を<br />に変える方法

    テキストエリアで改行した際に以下のコードですと改行は<br>になります。 これを<br />に変更したいのですが、自分なりに試してみたのですが全くうまくいきません。 sub decode { &ReadParse; while (($key,$val) = each %in) { if ($key !~ /upfile/ ) { &Jcode'convert(*val, "utf8", "", "z"); if ( $key !~ /label_name/ ) { $val =~ s/</&lt;/g; $val =~ s/>/&gt;/g; } $val =~ s/\r\n/<br>/g; $val =~ s/\r|\n/<br>/g; } $in{"$key"} = "$val"; } どなたか<br />に変更する記述を教えて頂けませんでしょうか?

    • 締切済み
    • CGI
  • csvファイル改行コードの置換について

    お世話になります。 csvファイルで作成したデータを出力表示させるスクリプトで csvファイル内の改行コード(セル内)以後のデータが出力できません。 下記の置換で改行コード以後のデータが表示されません。 $abc =~ s/\r\n//g; $abc =~ s/\n//g; $abc =~ s/\r//g; csvファイル内の改行の数が多く、1行のデータが改行の為に、2行になったりしているので出力前に置換し表示させる方法です。 csvファイル作成時につく""は正常に置換しています。 似たような質問もあったのですが、少し違うようですので質問いたしました。 何卒、ご教授お願いいたします。

    • ベストアンサー
    • Perl
  • 級数の計算

    例えば r=1.1のとき A(1)=3 A(2)=3*4.1=3*(3+1.1*1) A(3)=3*4.1*5.2=3*(3+1.1)*(3+1.1*2) A(4)=3*4.1*5.2*6.3=3*(3+1.1)*(3+1.1*2)*(3+1.1*3) A(n) = A(n)*(A(n)+r*(n-1)) 合っているかな? において A(n) = p となるrを計算したい。実際に使用するnは3から5程度なので個別のnで計算(プログラム)しても良い。 高校数学程度なのでしょうが、もう頭が回らなくなっているので教えて下さい。 自分の考えたところは n=4のとき、s=A(1)、y=A(4)として p = s*(s+r)*(s+2r)*(s+3r) 両辺の対数をとって log(p) = log(s)+log(s+r)+log(s+2r)+log(s+3r) としたとき、log(s+r) をlog(r)の式で表現できれば良いのでしょうが、これで躓いています。

専門家に質問してみよう