- ベストアンサー
変数に格納したいです。
[data.txtの中身] 485**954**afr**yhc**<>**0 197**875**erw**ihg**<>**0 854**430**otg**rtu**<>**0 ・ ・ EOF --------------------------------- 上記のファイルを読み込んで各行の先頭から4項目までを $data[0] $data[1] $data[2] $data[3] にそれぞれ格納したいです。 どのようにすればよいでしょうか?
- みんなの回答 (9)
- 専門家の回答
質問者が選んだベストアンサー
一応出てますけどとりあえず書いときますね(^^) **でも出来ましたのでdata.txtの中身 485**954**afr**yhc**<>**0** のように最後『**』を全部に付け足してください open(IN,"./data.txt"); @data=<IN>; close(IN); $num=@data; @tmp = map { (split /\*\*/) [0]} @data; @data = @data[sort {$tmp[$a] <=> $tmp[$b]} 0..$#tmp]; $i=0; foreach(@data) { ($n1,$n2,$n3,$n4,$n5,$n6)=split(/\*\*/); push(@data0,"$n1,"); push(@data1,"$n2,"); push(@data2,"$n3,"); push(@data3,"$n4,"); $i++; if($i eq "$num"){ last; } } open(OUT,">./out.txt"); for($i=0;$i<$num;++$i){ print OUT "$data0[$i]$data1[$i]$data2[$i]$data3[$i]\n"; } close(OUT); で 197,875,erw,ihg, 294,954,afr,yhc, 358,875,erw,ihg, 485,954,afr,yhc, 775,430,otg,rtu, 854,430,otg,rtu, のように書き込まれました(^^) $numのところはあれだったら $num=@data; $num=$num-1; にしておいてください
その他の回答 (8)
- sakusaker7
- ベストアンサー率62% (800/1280)
Perlはよく言えば柔軟、悪く言えばいい加減なので、 "123," のような文字列を数値として解釈しようとすると ちゃんと 123 になります。 ですので、 #8のスクリプトは open(IN,"./data.txt") or die; @data=<IN>; close(IN); #$num = scalar(@data) - 1; $num = scalar @data; $i=0; foreach (@data) { ($n1, $n2, $n3, $n4, undef, undef) = split(/\*\*/); push(@data0, "$n1,"); push(@data1, "$n2,"); push(@data2, "$n3,"); push(@data3, "$n4,"); $i++; last if ($i == $num) } @indeces = sort {$data0[$a] cmp $data0[$b]} 0..$#data0; open(OUT,">./out.txt") or die; foreach $index (@indeces){ print OUT "$data0[$index]$data1[$index]$data2[$index]$data3[$index]\n"; } close(OUT); のようにもできます。 まあ参考までに。 ところでこのスクリプトだと、行末に','が必ずくっつきますけど それはいいんですか?
お礼
たびたびご回答ありがとうございます。 >行末に','が必ずくっつきますけどそれはいいんですか? 大丈夫です。 おかげさまで、並べ替えもうまくいき、予定以上の結果が得ることができました。 すばらしいスクリプトをご教授頂きありがとうございました。 自分の環境に合わせて調整して使います。 本当に心より感謝申し上げます。 またこの場をお借りして質問することがあるかとも思いますが、 その節はよろしくお願いいたします。
- sakusaker7
- ベストアンサー率62% (800/1280)
ああすみません並べ替えのところを見落としていました。 もちろん可能ですよ。 私の先のスクリプトをちょっと変更して以下のようにすれば 多分お望みのように並ぶのではないかと。 use strict; use warnings; my $fh; #open $fh, '<', 'data.txt' or die "can't open date file: $!\n"; $fh = *DATA; my @data; my $maxcol = 4; my $lineno = 0; while (<$fh>) { my $sep = quotemeta '**'; my @tmp = split $sep, $_, $maxcol+1; pop @tmp; push @{$data[$lineno]}, @tmp; $lineno++; } print "並べ替え前\n"; foreach my $line_ref (@data) { print join(',', @{$line_ref}), "\n"; } my @sorted = sort {$a->[0] <=> $b->[0]} @data; print "並べ替え後\n"; foreach my $line_ref (@sorted) { print join(',', @{$line_ref}), "\n"; } __END__ 485**954**afr**yhc**<>**0 197**875**erw**ihg**<>**0 854**430**otg**rtu**<>**0 294**954**afr**yhc**<>**0 358**875**erw**ihg**<>**0 775**430**otg**rtu**<>**0 実行結果: 並べ替え前 485,954,afr,yhc 197,875,erw,ihg 854,430,otg,rtu 294,954,afr,yhc 358,875,erw,ihg 775,430,otg,rtu 並べ替え後 197,875,erw,ihg 294,954,afr,yhc 358,875,erw,ihg 485,954,afr,yhc 775,430,otg,rtu 854,430,otg,rtu
お礼
おかげさまで、並べ替えもうまくいき、予定以上の結果が得ることができました。 私のたよりない説明にもかかわらず、すばらしいスクリプトをご教授頂きありがとうございました。 自分の環境に合わせて調整して使います。 本当に心より感謝申し上げます。 またこの場をお借りして質問することがあるかとも思いますが、 その節はよろしくお願いいたします。
- sakusaker7
- ベストアンサー率62% (800/1280)
すみません確認させてください。 最終的にほしいのは、 485**954**afr**yhc**<>**0 197**875**erw**ihg**<>**0 854**430**otg**rtu**<>**0 ・ ・ というフォーマットのファイル(data.txt)の各行の最初の4つの要素 (各要素は '**'で区切られる)を、out.datというファイルに 各要素は ' ' (スペース一個)で区切って data.txtの最後の一行以外を除いて出力する。 ということですか? あと質問のdata.txtの説明に'EOF'というのがありますけど、 ひょっとしてdata.txtの最後の行に本当に'EOF' という文字列が おかれていたりするのでしょうか?
お礼
いつもありがとうございます。 >各要素は ' ' (スペース一個)で区切って 実際には@pushのところで加工していますのでその書き出しにはなりません。私の説明力が足らず申し訳ございません。 >data.txtの最後の行に本当に'EOF' という文字列が・・ すいません。これも私の間違いです。 正確には行末にEOFではなく[*****_DATA_FAIL_]と記述されています。重ね重ねお詫び申し上げます。 しかし皆様のご教授により目標の結果が得られました。 心より感謝申し上げます。 また先にも書きましたが最初の項目が整数に限定されているとしたら、 昇順に並べ替えて出力とかできるのでしょうか? 恐縮ですが、もし可能ならご教授いただければ幸いです。
- leap_day
- ベストアンサー率60% (338/561)
>どのように記述すれば(全行数-1)分だけout.datへの出力できますでしょうか? forを使えばできると思います open(OUT,">./out.dat"); for($i=0; $i<n; ++$i){ print OUT "$data0[$i]$data1[$i]$data2[$i]$data3[$i]\n"; } close(OUT); n に繰り返したい数値を入れればいいです 質問を見ている限りdata.txtとout.datの数は同じなので(何でEOFまで読み込まれるのか不思議ですけど(--;) open(IN,"./data.txt"); @data=<IN>; close(IN); $num=@data; $num=$num-1; for($i=0; $i<$num; ++$i) で全行-1指定できると思います
お礼
おかげさまで当初の予定通りの結果が得られるようになりました。 感謝いたします。ありがとうございました。 ちょっと思ったんですが、最初の項目が整数に限定されているとしたら、 昇順に並べ替えて出力とかできるのでしょうか? 恐縮ですが、もし可能ならご教授いただければ幸いです。 例 [data.txt] 485**954**afr**yhc**<>**0 197**875**erw**ihg**<>**0 854**430**otg**rtu**<>**0 294**954**afr**yhc**<>**0 358**875**erw**ihg**<>**0 775**430**otg**rtu**<>**0 ・ ・ ↓ [out.dat] 197,875,erw,ihg 294,954,afr,yhc 358,875,erw,ihg 485,954,afr,yhc 775,430,otg,rtu 854,430,otg,rtu ・ ・
- leap_day
- ベストアンサー率60% (338/561)
えとちょっと説明不足のようなので仮定で話します $data0[0] $data1[0] $data2[0] $data3[0]が出てくるので自分のを使ってるとして 『out.dat』には 485, 954, afr, yhc, 197, 875, erw, ihg, 854, 430, otg, rtu, 542, 653, jky, kgi, ・ ・ ・ という風に格納されてるのでしょうか? 『out.txt』を作ってopen(OUT,">./out.dat");をopen(OUT,">./out.txt");とすればどういう風に書き込まれてるか 確認できます(DATファイルだと確認しづらいので) >またこのままでは@data0に読み込まれたdata.txtの行末の「EOF」まで書き出されてしまうので これを出力しないようにしたいです。 $i=0; foreach(@data) { ($n1,$n2,$n3,$n4,$n5,$n6)=split(/<>/); push(@data0,"$n1,"); push(@data1,"$n2,"); push(@data2,"$n3,"); push(@data3,"$n4,"); $i++; if($i eq "3"){ last; } } のようにすればdata.txt全部でなく上から3行目までという風に操作することはできます
お礼
ありがとうございます。 out.datへの出力はご指摘のとおりです。 >data.txt全部でなく上から3行目までという風に操作することはできます data.txtの行数がその都度不確定なので、(全行数-1)でうまく読み込めました。 print OUT "$data0[0] $data1[0] $data2[0] $data3[0]\n";の部分を どのように記述すれば(全行数-1)分だけout.datへの出力できますでしょうか?
- sakusaker7
- ベストアンサー率62% (800/1280)
最終的にどういう出力をしたいかの具体例を補足していただければ、もうちょっとお望みに近いものに できると思いますが、とりあえずこんな感じで use strict; my $fh; #open $fh, '<', 'data.txt' or die "can't open date file: $!\n"; $fh = *DATA; my @data; my $maxcol = 4; while (<DATA>) { my $sep = quotemeta '**'; my @tmp = split $sep, $_, $maxcol+1; pop @tmp; my $col; foreach my $item (@tmp) { push @{$data[$col]}, $item; $col++; } } #use Dumpvalue; #my $d = new Dumpvalue; #$d->dumpValue(\@data); print "一列目のデータ:", join(',', @{$data[0]}), "\n"; print "二列目のデータ:", join(',', @{$data[1]}), "\n"; print "三列目のデータ:", join(',', @{$data[2]}), "\n"; print "四列目のデータ:", join(',', @{$data[3]}), "\n"; __END__ 485**954**afr**yhc**<>**0 197**875**erw**ihg**<>**0 854**430**otg**rtu**<>**0 出力結果: 一列目のデータ:485,197,854 二列目のデータ:954,875,430 三列目のデータ:afr,erw,otg 四列目のデータ:yhc,ihg,rtu のように一つの変数(@data)に納めることはできます。 デバッグ時にファイル作るの面倒なのでちょっとごまかしてますがその辺は御容赦。 openの行を有効にして*DATAを代入しているところをコメントアウトすれば大丈夫だと思いますが。
お礼
たびたびありがとうございます。 いまのところ上記のとおりです。 どうぞよろしくお願いいたします。
- leap_day
- ベストアンサー率60% (338/561)
open(IN,"./data.txt"); @data=<IN>; close(IN); foreach(@data) { ($n1,$n2,$n3,$n4,$n5,$n6)=split(/<>/); push(@data0,"$n1,"); push(@data1,"$n2,"); push(@data2,"$n3,"); push(@data3,"$n4,"); } print <<"EOM"; @data0<br> @data1<br> @data2<br> @data3 EOM とすれば 485, 197, 854, 954, 875, 430, afr, erw, otg, yhc, ihg, rtu, と表示されます 485**954**afr**yhc**<>**0 だと分離できませんでしたので 485<>954<>afr<>yhc<><>0<> に書き換えました(><) あと$data[0] ですが これは例えばdata.txtの内容を@dataに格納したときの1番初め(上)の配列を表す描き方です print "$data[0]\n"; とすると 485<>954<>afr<>yhc<>2<>0<> が表示されます @data0のところを$data0や$data[0]のようにするとサーバーエラーになります(==;)
お礼
ありがとうございます。 いろいろ試している最中で、配列への格納時に加工して いまのところこんな感じで出力すると思ったとおりになります。 ------------------------------------------------------- open(OUT,"> out.dat"); print OUT "$data0[0] $data1[0] $data2[0] $data3[0]\n"; print OUT "$data0[1] $data1[1] $data2[1] $data3[1]\n"; print OUT "$data0[2] $data1[2] $data2[2] $data3[2]\n"; print OUT "$data0[3] $data1[3] $data2[3] $data3[3]\n"; ・ ・ ・ ・(以下最終データまで) close(OUT); ------------------------------------------------------- これを最終データまで出力するにはまた新たに配列に入れればいいのでしょうか? またこのままでは@data0に読み込まれたdata.txtの行末の「EOF」まで書き出されてしまうので これを出力しないようにしたいです。 どうかよろしくお願いいたします。
- sakusaker7
- ベストアンサー率62% (800/1280)
data という配列に各行の四要素だけを格納したいというのはわかりますが、 違う行のデータはどうするのですか? 質問にある例を考えると、一行分しか保持できませんが。 dataを二次元配列にしたいとかの条件が抜けていませんか?
お礼
質問がわかりにくくてすいません。 >違う行のデータはどうするのですか? >質問にある例を考えると、一行分しか保持できませんが。 そうなんですか。配列自体がよくわからず困っています。 やりたいことは抜き出した4要素を加工して一覧を別ファイルに出力したいんです。 $data[0]=(485,197,854,・・・) $data[1]=(954,875,430,・・・) $data[2]=(afr,erw,otg,・・・) $data[3]=(yhc,ihg,rtu,・・・) このように格納できれば print "<b>",$data[3],"</b>",$data[1],$data[0],$data[2]; のような記述とかでデータ一覧が出力できるのかなと思いまして・・・。 よろしくお願いします。
お礼
おかげさまで、並べ替えもうまくいき、予定以上の結果が得ることができました。 私のたよりない説明にもかかわらず、すばらしいスクリプトをご教授頂きありがとうございました。 自分の環境に合わせて調整して使います。 本当に心より感謝申し上げます。 またこの場をお借りして質問することがあるかとも思いますが、 その節はよろしくお願いいたします。